From 22cb4ffc026b1fb71549031f174dc92f3751db56 Mon Sep 17 00:00:00 2001 From: wangkx1 Date: Tue, 13 Aug 2024 09:29:23 +0000 Subject: [PATCH] remove v0.3.5 --- ollama/.dockerignore | 9 - ollama/.gitattributes | 3 - .../.github/ISSUE_TEMPLATE/10_bug_report.yml | 60 - .../ISSUE_TEMPLATE/20_feature_request.md | 6 - .../ISSUE_TEMPLATE/30_model_request.md | 5 - ollama/.github/ISSUE_TEMPLATE/config.yml | 8 - ollama/.github/workflows/latest.yaml | 24 - ollama/.github/workflows/release.yaml | 480 - ollama/.github/workflows/test.yaml | 323 - ollama/.gitignore | 15 - ollama/.gitmodules | 4 - ollama/.golangci.yaml | 44 - ollama/.prettierrc.json | 10 - ollama/Dockerfile | 144 - ollama/LICENSE | 21 - ollama/README.md | 409 - ollama/SECURITY.md | 25 - ollama/api/client.go | 380 - ollama/api/client_test.go | 45 - ollama/api/types.go | 731 - ollama/api/types_test.go | 233 - ollama/app/.gitignore | 1 - ollama/app/README.md | 22 - ollama/app/assets/app.ico | Bin 7502 -> 0 bytes ollama/app/assets/assets.go | 17 - ollama/app/assets/setup.bmp | Bin 77418 -> 0 bytes ollama/app/assets/tray.ico | Bin 91014 -> 0 bytes ollama/app/assets/tray_upgrade.ico | Bin 92898 -> 0 bytes ollama/app/lifecycle/getstarted_nonwindows.go | 9 - ollama/app/lifecycle/getstarted_windows.go | 43 - ollama/app/lifecycle/lifecycle.go | 92 - ollama/app/lifecycle/logging.go | 80 - ollama/app/lifecycle/logging_nonwindows.go | 9 - ollama/app/lifecycle/logging_test.go | 44 - ollama/app/lifecycle/logging_windows.go | 19 - ollama/app/lifecycle/paths.go | 79 - ollama/app/lifecycle/server.go | 180 - ollama/app/lifecycle/server_unix.go | 38 - ollama/app/lifecycle/server_windows.go | 91 - ollama/app/lifecycle/updater.go | 229 - ollama/app/lifecycle/updater_nonwindows.go | 12 - ollama/app/lifecycle/updater_windows.go | 78 - ollama/app/main.go | 12 - ollama/app/ollama.iss | 165 - ollama/app/ollama.rc | 29 - ollama/app/ollama_welcome.ps1 | 8 - ollama/app/store/store.go | 97 - ollama/app/store/store_darwin.go | 13 - ollama/app/store/store_linux.go | 16 - ollama/app/store/store_windows.go | 11 - ollama/app/tray/commontray/types.go | 24 - ollama/app/tray/tray.go | 28 - ollama/app/tray/tray_nonwindows.go | 13 - ollama/app/tray/tray_windows.go | 10 - ollama/app/tray/wintray/eventloop.go | 181 - ollama/app/tray/wintray/menus.go | 71 - ollama/app/tray/wintray/messages.go | 15 - ollama/app/tray/wintray/notifyicon.go | 66 - ollama/app/tray/wintray/tray.go | 482 - ollama/app/tray/wintray/w32api.go | 89 - ollama/app/tray/wintray/winclass.go | 45 - ollama/auth/auth.go | 92 - ollama/cmd/cmd.go | 1383 - ollama/cmd/interactive.go | 622 - ollama/cmd/interactive_test.go | 107 - ollama/cmd/start.go | 27 - ollama/cmd/start_darwin.go | 30 - ollama/cmd/start_default.go | 14 - ollama/cmd/start_windows.go | 58 - ollama/convert/convert.go | 122 - ollama/convert/convert_gemma.go | 103 - ollama/convert/convert_llama.go | 183 - ollama/convert/convert_mixtral.go | 89 - ollama/convert/convert_test.go | 128 - ollama/convert/fs.go | 58 - ollama/convert/reader.go | 82 - ollama/convert/reader_safetensors.go | 150 - ollama/convert/reader_torch.go | 47 - .../sentencepiece/sentencepiece_model.pb.go | 1497 - ollama/convert/sentencepiece_model.proto | 333 - .../testdata/Meta-Llama-3-8B-Instruct.json | 313 - .../testdata/Mistral-7B-Instruct-v0.2.json | 313 - .../testdata/Mixtral-8x7B-Instruct-v0.1.json | 348 - ollama/convert/testdata/gemma-2b-it.json | 188 - ollama/convert/tokenizer.go | 265 - ollama/convert/tokenizer_spm.go | 83 - ollama/docs/README.md | 21 - ollama/docs/api.md | 1293 - ollama/docs/development.md | 150 - ollama/docs/docker.md | 71 - ollama/docs/faq.md | 279 - ollama/docs/gpu.md | 113 - ollama/docs/import.md | 88 - ollama/docs/linux.md | 143 - ollama/docs/modelfile.md | 227 - ollama/docs/openai.md | 303 - ollama/docs/template.md | 173 - ollama/docs/troubleshooting.md | 96 - ollama/docs/tutorials.md | 9 - ollama/docs/tutorials/fly-gpu.md | 83 - ollama/docs/tutorials/langchainjs.md | 77 - ollama/docs/tutorials/langchainpy.md | 85 - ollama/docs/tutorials/nvidia-jetson.md | 15 - ollama/docs/windows.md | 63 - ollama/envconfig/config.go | 284 - ollama/envconfig/config_test.go | 235 - ollama/examples/.gitignore | 174 - ollama/examples/README.md | 3 - ollama/examples/flyio/.gitignore | 1 - ollama/examples/flyio/README.md | 67 - ollama/examples/go-chat/main.go | 51 - ollama/examples/go-generate-streaming/main.go | 40 - ollama/examples/go-generate/main.go | 37 - ollama/examples/go-http-generate/main.go | 29 - ollama/examples/go-multimodal/main.go | 47 - ollama/examples/go-pull-progress/main.go | 31 - ollama/examples/jupyter-notebook/README.md | 5 - ollama/examples/jupyter-notebook/ollama.ipynb | 102 - ollama/examples/kubernetes/README.md | 38 - ollama/examples/kubernetes/cpu.yaml | 42 - ollama/examples/kubernetes/gpu.yaml | 58 - .../langchain-python-rag-document/README.md | 29 - .../langchain-python-rag-document/main.py | 61 - .../requirements.txt | 109 - .../.gitignore | 170 - .../langchain-python-rag-privategpt/LICENSE | 201 - .../langchain-python-rag-privategpt/README.md | 91 - .../constants.py | 11 - .../langchain-python-rag-privategpt/ingest.py | 170 - .../poetry.lock | 3833 --- .../privateGPT.py | 74 - .../pyproject.toml | 26 - .../requirements.txt | 15 - .../langchain-python-rag-websummary/README.md | 23 - .../langchain-python-rag-websummary/main.py | 12 - .../requirements.txt | 1 - .../langchain-python-simple/README.md | 23 - .../examples/langchain-python-simple/main.py | 6 - .../langchain-python-simple/requirements.txt | 1 - .../langchain-typescript-simple/README.md | 23 - .../langchain-typescript-simple/main.ts | 25 - .../package-lock.json | 997 - .../langchain-typescript-simple/package.json | 13 - ollama/examples/modelfile-mario/Modelfile | 5 - ollama/examples/modelfile-mario/logo.png | Bin 456296 -> 0 bytes ollama/examples/modelfile-mario/readme.md | 43 - ollama/examples/python-dockerit/Modelfile | 20 - ollama/examples/python-dockerit/README.md | 31 - ollama/examples/python-dockerit/dockerit.py | 17 - .../examples/python-dockerit/requirements.txt | 1 - .../predefinedschema.py | 31 - .../randomaddresses.py | 31 - .../python-json-datagenerator/readme.md | 60 - .../requirements.txt | 1 - ollama/examples/python-loganalysis/Modelfile | 8 - .../python-loganalysis/loganalysis.py | 41 - .../python-loganalysis/logtest.logfile | 32 - ollama/examples/python-loganalysis/readme.md | 70 - .../python-loganalysis/requirements.txt | 1 - .../examples/python-rag-newssummary/README.md | 35 - .../python-rag-newssummary/requirements.txt | 9 - .../examples/python-rag-newssummary/summ.py | 86 - .../examples/python-rag-newssummary/utils.py | 108 - ollama/examples/python-simplechat/client.py | 48 - ollama/examples/python-simplechat/readme.md | 44 - .../python-simplechat/requirements.txt | 1 - .../examples/python-simplegenerate/README.md | 29 - .../examples/python-simplegenerate/client.py | 40 - .../python-simplegenerate/requirements.txt | 1 - .../extractemail.ts | 118 - .../typescript-functioncalling/extractwp.ts | 38 - .../typescript-functioncalling/info.txt | 17 - .../package-lock.json | 519 - .../typescript-functioncalling/package.json | 9 - .../typescript-functioncalling/readme.md | 28 - .../typescript-functioncalling/wp.txt | 183 - ollama/examples/typescript-mentors/.gitignore | 2 - ollama/examples/typescript-mentors/README.md | 65 - .../typescript-mentors/character-generator.ts | 26 - ollama/examples/typescript-mentors/mentors.ts | 60 - .../examples/typescript-mentors/package.json | 15 - .../examples/typescript-simplechat/client.ts | 77 - .../typescript-simplechat/package.json | 12 - .../examples/typescript-simplechat/readme.md | 35 - ollama/format/bytes.go | 65 - ollama/format/format.go | 34 - ollama/format/format_test.go | 33 - ollama/format/time.go | 70 - ollama/format/time_test.go | 45 - ollama/go.mod | 78 - ollama/go.sum | 364 - ollama/gpu/amd_common.go | 99 - ollama/gpu/amd_hip_windows.go | 147 - ollama/gpu/amd_linux.go | 460 - ollama/gpu/amd_windows.go | 192 - ollama/gpu/assets.go | 148 - ollama/gpu/cpu_common.go | 37 - ollama/gpu/cuda_common.go | 21 - ollama/gpu/gpu.go | 643 - ollama/gpu/gpu_darwin.go | 68 - ollama/gpu/gpu_info.h | 70 - ollama/gpu/gpu_info_cudart.c | 183 - ollama/gpu/gpu_info_cudart.h | 148 - ollama/gpu/gpu_info_darwin.h | 5 - ollama/gpu/gpu_info_darwin.m | 35 - ollama/gpu/gpu_info_nvcuda.c | 243 - ollama/gpu/gpu_info_nvcuda.h | 79 - ollama/gpu/gpu_info_nvml.c | 104 - ollama/gpu/gpu_info_nvml.h | 48 - ollama/gpu/gpu_info_oneapi.c | 259 - ollama/gpu/gpu_info_oneapi.h | 203 - ollama/gpu/gpu_linux.go | 92 - ollama/gpu/gpu_oneapi.go | 21 - ollama/gpu/gpu_test.go | 35 - ollama/gpu/gpu_windows.go | 57 - ollama/gpu/types.go | 145 - ollama/integration/README.md | 11 - ollama/integration/basic_test.go | 63 - ollama/integration/concurrency_test.go | 270 - ollama/integration/context_test.go | 34 - ollama/integration/embed_test.go | 209 - ollama/integration/llm_image_test.go | 537 - ollama/integration/llm_test.go | 47 - ollama/integration/max_queue_test.go | 120 - ollama/integration/utils_test.go | 343 - ollama/llm/ext_server/CMakeLists.txt | 13 - ollama/llm/ext_server/httplib.h | 8794 ------ ollama/llm/ext_server/json.hpp | 24596 --------------- ollama/llm/ext_server/server.cpp | 3261 -- ollama/llm/ext_server/utils.hpp | 658 - ollama/llm/filetype.go | 180 - ollama/llm/generate/gen_common.sh | 119 - ollama/llm/generate/gen_darwin.sh | 101 - ollama/llm/generate/gen_linux.sh | 284 - ollama/llm/generate/gen_windows.ps1 | 423 - ollama/llm/generate/generate_darwin.go | 3 - ollama/llm/generate/generate_linux.go | 3 - ollama/llm/generate/generate_windows.go | 3 - ollama/llm/ggla.go | 149 - ollama/llm/ggml.go | 459 - ollama/llm/ggml_test.go | 1 - ollama/llm/gguf.go | 663 - ollama/llm/llama.cpp/.clang-tidy | 24 - ollama/llm/llama.cpp/.devops/cloud-v-pipeline | 22 - .../llama.cpp/.devops/full-cuda.Dockerfile | 36 - .../llama.cpp/.devops/full-rocm.Dockerfile | 50 - ollama/llm/llama.cpp/.devops/full.Dockerfile | 25 - .../.devops/llama-cli-cuda.Dockerfile | 35 - .../.devops/llama-cli-intel.Dockerfile | 28 - .../.devops/llama-cli-rocm.Dockerfile | 45 - .../.devops/llama-cli-vulkan.Dockerfile | 27 - .../llama.cpp/.devops/llama-cli.Dockerfile | 23 - .../.devops/llama-cpp-cuda.srpm.spec | 83 - .../llm/llama.cpp/.devops/llama-cpp.srpm.spec | 85 - .../.devops/llama-server-cuda.Dockerfile | 39 - .../.devops/llama-server-intel.Dockerfile | 32 - .../.devops/llama-server-rocm.Dockerfile | 52 - .../.devops/llama-server-vulkan.Dockerfile | 29 - .../llama.cpp/.devops/llama-server.Dockerfile | 27 - ollama/llm/llama.cpp/.devops/nix/apps.nix | 21 - .../llm/llama.cpp/.devops/nix/devshells.nix | 13 - ollama/llm/llama.cpp/.devops/nix/docker.nix | 37 - .../llama.cpp/.devops/nix/jetson-support.nix | 39 - .../.devops/nix/nixpkgs-instances.nix | 47 - ollama/llm/llama.cpp/.devops/nix/package.nix | 324 - ollama/llm/llama.cpp/.devops/nix/scope.nix | 19 - ollama/llm/llama.cpp/.devops/nix/sif.nix | 27 - ollama/llm/llama.cpp/.devops/tools.sh | 41 - ollama/llm/llama.cpp/.dockerignore | 20 - ollama/llm/llama.cpp/.ecrc | 6 - ollama/llm/llama.cpp/.editorconfig | 32 - ollama/llm/llama.cpp/.flake8 | 17 - .../.github/ISSUE_TEMPLATE/01-bug-low.yml | 50 - .../.github/ISSUE_TEMPLATE/02-bug-medium.yml | 50 - .../.github/ISSUE_TEMPLATE/03-bug-high.yml | 50 - .../ISSUE_TEMPLATE/04-bug-critical.yml | 50 - .../.github/ISSUE_TEMPLATE/05-enhancement.yml | 51 - .../.github/ISSUE_TEMPLATE/06-research.yml | 52 - .../.github/ISSUE_TEMPLATE/07-refactor.yml | 28 - .../.github/ISSUE_TEMPLATE/config.yml | 11 - ollama/llm/llama.cpp/.github/labeler.yml | 91 - .../.github/pull_request_template.md | 7 - .../llm/llama.cpp/.github/workflows/bench.yml | 310 - .../llm/llama.cpp/.github/workflows/build.yml | 1316 - .../.github/workflows/close-issue.yml | 23 - .../llama.cpp/.github/workflows/docker.yml | 116 - .../.github/workflows/editorconfig.yml | 27 - .../.github/workflows/gguf-publish.yml | 44 - .../llama.cpp/.github/workflows/labeler.yml | 17 - .../.github/workflows/nix-ci-aarch64.yml | 65 - .../llama.cpp/.github/workflows/nix-ci.yml | 72 - .../.github/workflows/nix-flake-update.yml | 22 - .../.github/workflows/nix-publish-flake.yml | 36 - .../workflows/python-check-requirements.yml | 35 - .../.github/workflows/python-lint.yml | 23 - .../.github/workflows/python-type-check.yml | 38 - .../llama.cpp/.github/workflows/server.yml | 183 - ollama/llm/llama.cpp/.gitignore | 132 - ollama/llm/llama.cpp/.gitmodules | 3 - ollama/llm/llama.cpp/.pre-commit-config.yaml | 16 - ollama/llm/llama.cpp/AUTHORS | 782 - ollama/llm/llama.cpp/CMakeLists.txt | 201 - ollama/llm/llama.cpp/CMakePresets.json | 65 - ollama/llm/llama.cpp/CONTRIBUTING.md | 29 - ollama/llm/llama.cpp/LICENSE | 21 - ollama/llm/llama.cpp/Makefile | 1647 - ollama/llm/llama.cpp/Package.swift | 79 - ollama/llm/llama.cpp/README.md | 483 - ollama/llm/llama.cpp/SECURITY.md | 67 - ollama/llm/llama.cpp/ci/README.md | 29 - ollama/llm/llama.cpp/ci/run.sh | 775 - .../llama.cpp/cmake/arm64-windows-llvm.cmake | 16 - .../llama.cpp/cmake/arm64-windows-msvc.cmake | 6 - ollama/llm/llama.cpp/cmake/build-info.cmake | 58 - ollama/llm/llama.cpp/cmake/git-vars.cmake | 22 - .../llm/llama.cpp/cmake/llama-config.cmake.in | 90 - ollama/llm/llama.cpp/cmake/llama.pc.in | 10 - ollama/llm/llama.cpp/common/CMakeLists.txt | 88 - ollama/llm/llama.cpp/common/base64.hpp | 392 - ollama/llm/llama.cpp/common/build-info.cpp.in | 4 - ollama/llm/llama.cpp/common/common.cpp | 3256 -- ollama/llm/llama.cpp/common/common.h | 474 - ollama/llm/llama.cpp/common/console.cpp | 501 - ollama/llm/llama.cpp/common/console.h | 19 - .../llm/llama.cpp/common/grammar-parser.cpp | 536 - ollama/llm/llama.cpp/common/grammar-parser.h | 29 - .../common/json-schema-to-grammar.cpp | 1045 - .../llama.cpp/common/json-schema-to-grammar.h | 8 - ollama/llm/llama.cpp/common/json.hpp | 24766 ---------------- ollama/llm/llama.cpp/common/log.h | 724 - ollama/llm/llama.cpp/common/ngram-cache.cpp | 282 - ollama/llm/llama.cpp/common/ngram-cache.h | 101 - ollama/llm/llama.cpp/common/sampling.cpp | 460 - ollama/llm/llama.cpp/common/sampling.h | 160 - ollama/llm/llama.cpp/common/stb_image.h | 8396 ------ ollama/llm/llama.cpp/common/train.cpp | 1513 - ollama/llm/llama.cpp/common/train.h | 233 - ollama/llm/llama.cpp/convert_hf_to_gguf.py | 3823 --- .../llama.cpp/convert_hf_to_gguf_update.py | 351 - .../llama.cpp/convert_llama_ggml_to_gguf.py | 450 - ollama/llm/llama.cpp/convert_lora_to_gguf.py | 393 - ollama/llm/llama.cpp/docs/android.md | 56 - ollama/llm/llama.cpp/docs/backend/BLIS.md | 67 - ollama/llm/llama.cpp/docs/backend/SYCL.md | 580 - ollama/llm/llama.cpp/docs/build.md | 357 - .../docs/development/HOWTO-add-model.md | 119 - .../docs/development/debugging-tests.md | 104 - .../docs/development/llama-star/idea-arch.key | Bin 488591 -> 0 bytes .../docs/development/llama-star/idea-arch.pdf | Bin 42334 -> 0 bytes .../token_generation_performance_tips.md | 40 - ollama/llm/llama.cpp/docs/docker.md | 86 - ollama/llm/llama.cpp/docs/install.md | 39 - ollama/llm/llama.cpp/examples/CMakeLists.txt | 55 - ollama/llm/llama.cpp/examples/Miku.sh | 50 - .../examples/baby-llama/CMakeLists.txt | 5 - .../examples/baby-llama/baby-llama.cpp | 1639 - .../llm/llama.cpp/examples/base-translate.sh | 61 - .../examples/batched-bench/CMakeLists.txt | 5 - .../examples/batched-bench/README.md | 51 - .../examples/batched-bench/batched-bench.cpp | 215 - .../examples/batched.swift/.gitignore | 9 - .../llama.cpp/examples/batched.swift/Makefile | 6 - .../examples/batched.swift/Package.swift | 22 - .../examples/batched.swift/README.md | 4 - .../examples/batched.swift/Sources/main.swift | 262 - .../llama.cpp/examples/batched/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/batched/README.md | 44 - .../llama.cpp/examples/batched/batched.cpp | 259 - .../examples/benchmark/CMakeLists.txt | 6 - .../examples/benchmark/benchmark-matmult.cpp | 275 - ollama/llm/llama.cpp/examples/chat-13B.bat | 57 - ollama/llm/llama.cpp/examples/chat-13B.sh | 41 - .../llm/llama.cpp/examples/chat-persistent.sh | 151 - ollama/llm/llama.cpp/examples/chat-vicuna.sh | 41 - ollama/llm/llama.cpp/examples/chat.sh | 16 - .../convert-llama2c-to-ggml/CMakeLists.txt | 5 - .../convert-llama2c-to-ggml/README.md | 28 - .../convert-llama2c-to-ggml.cpp | 936 - .../examples/convert_legacy_llama.py | 1440 - .../examples/cvector-generator/CMakeLists.txt | 5 - .../examples/cvector-generator/README.md | 45 - .../cvector-generator/completions.txt | 582 - .../cvector-generator/cvector-generator.cpp | 504 - .../examples/cvector-generator/mean.hpp | 48 - .../examples/cvector-generator/negative.txt | 4 - .../examples/cvector-generator/pca.hpp | 325 - .../examples/cvector-generator/positive.txt | 4 - .../examples/deprecation-warning/README.md | 49 - .../deprecation-warning.cpp | 35 - .../examples/embedding/CMakeLists.txt | 5 - .../llama.cpp/examples/embedding/README.md | 60 - .../examples/embedding/embedding.cpp | 268 - .../examples/eval-callback/CMakeLists.txt | 9 - .../examples/eval-callback/README.md | 95 - .../examples/eval-callback/eval-callback.cpp | 194 - .../examples/export-lora/CMakeLists.txt | 5 - .../llama.cpp/examples/export-lora/README.md | 33 - .../examples/export-lora/export-lora.cpp | 420 - .../examples/gbnf-validator/CMakeLists.txt | 5 - .../gbnf-validator/gbnf-validator.cpp | 137 - .../examples/gguf-hash/CMakeLists.txt | 15 - .../llama.cpp/examples/gguf-hash/README.md | 206 - .../gguf-hash/deps/rotate-bits/package.json | 13 - .../gguf-hash/deps/rotate-bits/rotate-bits.h | 46 - .../examples/gguf-hash/deps/sha1/package.json | 9 - .../examples/gguf-hash/deps/sha1/sha1.c | 295 - .../examples/gguf-hash/deps/sha1/sha1.h | 52 - .../gguf-hash/deps/sha256/package.json | 15 - .../examples/gguf-hash/deps/sha256/sha256.c | 221 - .../examples/gguf-hash/deps/sha256/sha256.h | 24 - .../examples/gguf-hash/deps/xxhash/clib.json | 12 - .../examples/gguf-hash/deps/xxhash/xxhash.c | 42 - .../examples/gguf-hash/deps/xxhash/xxhash.h | 7093 ----- .../examples/gguf-hash/gguf-hash.cpp | 693 - .../examples/gguf-split/CMakeLists.txt | 5 - .../llama.cpp/examples/gguf-split/README.md | 10 - .../examples/gguf-split/gguf-split.cpp | 564 - .../llama.cpp/examples/gguf-split/tests.sh | 89 - .../llama.cpp/examples/gguf/CMakeLists.txt | 5 - ollama/llm/llama.cpp/examples/gguf/gguf.cpp | 261 - .../llama.cpp/examples/gritlm/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/gritlm/README.md | 62 - .../llm/llama.cpp/examples/gritlm/gritlm.cpp | 219 - .../llama.cpp/examples/imatrix/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/imatrix/README.md | 35 - .../llama.cpp/examples/imatrix/imatrix.cpp | 649 - .../llama.cpp/examples/infill/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/infill/README.md | 47 - .../llm/llama.cpp/examples/infill/infill.cpp | 655 - .../llm/llama.cpp/examples/jeopardy/README.md | 21 - .../llm/llama.cpp/examples/jeopardy/graph.py | 58 - .../llama.cpp/examples/jeopardy/jeopardy.sh | 30 - .../llama.cpp/examples/jeopardy/qasheet.csv | 103 - .../llama.cpp/examples/jeopardy/questions.txt | 100 - .../examples/json_schema_pydantic_example.py | 82 - .../examples/json_schema_to_grammar.py | 811 - .../examples/llama-bench/CMakeLists.txt | 5 - .../llama.cpp/examples/llama-bench/README.md | 281 - .../examples/llama-bench/llama-bench.cpp | 1455 - .../examples/llama.android/.gitignore | 33 - .../examples/llama.android/README.md | 0 .../examples/llama.android/app/.gitignore | 1 - .../llama.android/app/build.gradle.kts | 65 - .../llama.android/app/proguard-rules.pro | 21 - .../app/src/main/AndroidManifest.xml | 30 - .../java/com/example/llama/Downloadable.kt | 119 - .../java/com/example/llama/MainActivity.kt | 154 - .../java/com/example/llama/MainViewModel.kt | 105 - .../java/com/example/llama/ui/theme/Color.kt | 11 - .../java/com/example/llama/ui/theme/Theme.kt | 70 - .../java/com/example/llama/ui/theme/Type.kt | 34 - .../res/drawable/ic_launcher_background.xml | 170 - .../res/drawable/ic_launcher_foreground.xml | 30 - .../main/res/mipmap-anydpi/ic_launcher.xml | 6 - .../res/mipmap-anydpi/ic_launcher_round.xml | 6 - .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes .../app/src/main/res/values/colors.xml | 10 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/themes.xml | 5 - .../app/src/main/res/xml/backup_rules.xml | 13 - .../main/res/xml/data_extraction_rules.xml | 19 - .../examples/llama.android/build.gradle.kts | 6 - .../examples/llama.android/gradle.properties | 23 - .../gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../llama.cpp/examples/llama.android/gradlew | 185 - .../examples/llama.android/llama/.gitignore | 1 - .../llama.android/llama/build.gradle.kts | 68 - .../llama.android/llama/consumer-rules.pro | 0 .../llama.android/llama/proguard-rules.pro | 21 - .../llama/cpp/ExampleInstrumentedTest.kt | 24 - .../llama/src/main/AndroidManifest.xml | 4 - .../llama/src/main/cpp/CMakeLists.txt | 53 - .../llama/src/main/cpp/llama-android.cpp | 443 - .../java/android/llama/cpp/LLamaAndroid.kt | 172 - .../java/android/llama/cpp/ExampleUnitTest.kt | 17 - .../llama.android/settings.gradle.kts | 18 - .../examples/llama.swiftui/.gitignore | 2 - .../examples/llama.swiftui/README.md | 12 - .../llama.cpp.swift/LibLlama.swift | 343 - .../llama.swiftui.xcodeproj/project.pbxproj | 439 - .../contents.xcworkspacedata | 7 - .../AppIcon.appiconset/Contents.json | 13 - .../Assets.xcassets/Contents.json | 6 - .../llama.swiftui/Models/LlamaState.swift | 196 - .../llama.swiftui/Resources/models/.gitignore | 0 .../llama.swiftui/UI/ContentView.swift | 145 - .../llama.swiftui/UI/DownloadButton.swift | 124 - .../llama.swiftui/UI/InputButton.swift | 131 - .../llama.swiftui/UI/LoadCustomButton.swift | 44 - .../llama.swiftui/llama_swiftuiApp.swift | 10 - ollama/llm/llama.cpp/examples/llama.vim | 135 - .../llama.cpp/examples/llava/CMakeLists.txt | 38 - .../examples/llava/MobileVLM-README.md | 377 - ollama/llm/llama.cpp/examples/llava/README.md | 139 - .../examples/llava/android/adb_run.sh | 53 - .../examples/llava/android/build_64.sh | 8 - ollama/llm/llama.cpp/examples/llava/clip.cpp | 2087 -- ollama/llm/llama.cpp/examples/llava/clip.h | 85 - .../llava/convert_image_encoder_to_gguf.py | 333 - .../llama.cpp/examples/llava/llava-cli.cpp | 340 - ollama/llm/llama.cpp/examples/llava/llava.cpp | 411 - ollama/llm/llama.cpp/examples/llava/llava.h | 50 - .../llama.cpp/examples/llava/llava_surgery.py | 38 - .../examples/llava/llava_surgery_v2.py | 159 - .../llama.cpp/examples/llava/requirements.txt | 4 - ollama/llm/llama.cpp/examples/llm.vim | 28 - .../examples/lookahead/CMakeLists.txt | 5 - .../llama.cpp/examples/lookahead/README.md | 7 - .../examples/lookahead/lookahead.cpp | 486 - .../llama.cpp/examples/lookup/CMakeLists.txt | 23 - .../llm/llama.cpp/examples/lookup/README.md | 12 - .../examples/lookup/lookup-create.cpp | 43 - .../examples/lookup/lookup-merge.cpp | 47 - .../examples/lookup/lookup-stats.cpp | 159 - .../llm/llama.cpp/examples/lookup/lookup.cpp | 257 - .../examples/main-cmake-pkg/.gitignore | 50 - .../examples/main-cmake-pkg/CMakeLists.txt | 32 - .../examples/main-cmake-pkg/README.md | 31 - .../llama.cpp/examples/main/CMakeLists.txt | 5 - ollama/llm/llama.cpp/examples/main/README.md | 319 - ollama/llm/llama.cpp/examples/main/main.cpp | 997 - .../examples/parallel/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/parallel/README.md | 3 - .../llama.cpp/examples/parallel/parallel.cpp | 428 - .../llama.cpp/examples/passkey/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/passkey/README.md | 15 - .../llama.cpp/examples/passkey/passkey.cpp | 282 - .../examples/perplexity/CMakeLists.txt | 5 - .../llama.cpp/examples/perplexity/README.md | 193 - .../examples/perplexity/perplexity.cpp | 2066 -- .../examples/pydantic_models_to_grammar.py | 1322 - .../pydantic_models_to_grammar_examples.py | 312 - .../examples/quantize-stats/CMakeLists.txt | 6 - .../quantize-stats/quantize-stats.cpp | 424 - .../examples/quantize/CMakeLists.txt | 6 - .../llm/llama.cpp/examples/quantize/README.md | 129 - .../llama.cpp/examples/quantize/quantize.cpp | 453 - .../llm/llama.cpp/examples/quantize/tests.sh | 65 - ollama/llm/llama.cpp/examples/reason-act.sh | 16 - .../llama.cpp/examples/regex_to_grammar.py | 20 - .../examples/retrieval/CMakeLists.txt | 5 - .../llama.cpp/examples/retrieval/README.md | 69 - .../examples/retrieval/retrieval.cpp | 300 - .../llm/llama.cpp/examples/rpc/CMakeLists.txt | 2 - ollama/llm/llama.cpp/examples/rpc/README.md | 74 - .../llm/llama.cpp/examples/rpc/rpc-server.cpp | 134 - .../examples/save-load-state/CMakeLists.txt | 5 - .../save-load-state/save-load-state.cpp | 254 - .../llama.cpp/examples/server-llama2-13B.sh | 26 - .../llama.cpp/examples/server/CMakeLists.txt | 64 - .../llm/llama.cpp/examples/server/README.md | 919 - .../llama.cpp/examples/server/bench/README.md | 120 - .../llama.cpp/examples/server/bench/bench.py | 312 - .../examples/server/bench/prometheus.yml | 9 - .../examples/server/bench/requirements.txt | 2 - .../llama.cpp/examples/server/bench/script.js | 150 - .../llama.cpp/examples/server/chat-llama2.sh | 109 - ollama/llm/llama.cpp/examples/server/chat.mjs | 131 - ollama/llm/llama.cpp/examples/server/chat.sh | 80 - ollama/llm/llama.cpp/examples/server/deps.sh | 10 - .../llm/llama.cpp/examples/server/httplib.h | 9465 ------ .../examples/server/public/colorthemes.css | 402 - .../examples/server/public/completion.js | 204 - .../examples/server/public/favicon.ico | Bin 4122 -> 0 bytes .../examples/server/public/index-new.html | 1178 - .../examples/server/public/index.html | 1293 - .../llama.cpp/examples/server/public/index.js | 1 - .../server/public/json-schema-to-grammar.mjs | 835 - .../examples/server/public/prompt-formats.js | 331 - .../examples/server/public/style.css | 954 - .../examples/server/public/system-prompts.js | 68 - .../server/public/theme-beeninorder.css | 228 - .../examples/server/public/theme-ketivah.css | 201 - .../server/public/theme-mangotango.css | 216 - .../server/public/theme-playground.css | 221 - .../server/public/theme-polarnight.css | 253 - .../server/public/theme-snowstorm.css | 251 - .../server/public_simplechat/datautils.mjs | 266 - .../server/public_simplechat/index.html | 51 - .../server/public_simplechat/readme.md | 286 - .../server/public_simplechat/simplechat.css | 79 - .../server/public_simplechat/simplechat.js | 926 - .../public_simplechat/simplechat_screens.webp | Bin 21376 -> 0 bytes .../examples/server/public_simplechat/ui.mjs | 211 - .../llm/llama.cpp/examples/server/server.cpp | 3515 --- .../llama.cpp/examples/server/tests/README.md | 65 - .../server/tests/features/embeddings.feature | 96 - .../server/tests/features/environment.py | 71 - .../server/tests/features/issues.feature | 5 - .../server/tests/features/lora.feature | 36 - .../server/tests/features/parallel.feature | 102 - .../server/tests/features/passkey.feature | 54 - .../server/tests/features/results.feature | 118 - .../server/tests/features/security.feature | 68 - .../server/tests/features/server.feature | 112 - .../server/tests/features/slotsave.feature | 58 - .../server/tests/features/steps/steps.py | 1381 - .../tests/features/wrong_usages.feature | 22 - .../examples/server/tests/requirements.txt | 7 - .../llama.cpp/examples/server/tests/tests.sh | 11 - .../examples/server/themes/README.md | 5 - .../server/themes/buttons-top/README.md | 7 - .../server/themes/buttons-top/buttons_top.png | Bin 119747 -> 0 bytes .../server/themes/buttons-top/favicon.ico | Bin 4122 -> 0 bytes .../server/themes/buttons-top/index.html | 1056 - .../examples/server/themes/wild/README.md | 5 - .../examples/server/themes/wild/favicon.ico | Bin 4122 -> 0 bytes .../examples/server/themes/wild/index.html | 1060 - .../examples/server/themes/wild/llama_cpp.png | Bin 76484 -> 0 bytes .../server/themes/wild/llamapattern.png | Bin 259586 -> 0 bytes .../examples/server/themes/wild/wild.png | Bin 496463 -> 0 bytes .../llm/llama.cpp/examples/server/utils.hpp | 636 - ollama/llm/llama.cpp/examples/server_embd.py | 35 - .../llama.cpp/examples/simple/CMakeLists.txt | 5 - .../llm/llama.cpp/examples/simple/README.md | 21 - .../llm/llama.cpp/examples/simple/simple.cpp | 175 - .../examples/speculative/CMakeLists.txt | 5 - .../llama.cpp/examples/speculative/README.md | 9 - .../examples/speculative/speculative.cpp | 619 - .../llama.cpp/examples/sycl/CMakeLists.txt | 9 - ollama/llm/llama.cpp/examples/sycl/README.md | 47 - ollama/llm/llama.cpp/examples/sycl/build.sh | 23 - .../examples/sycl/ls-sycl-device.cpp | 13 - .../llm/llama.cpp/examples/sycl/run-llama2.sh | 36 - .../examples/sycl/win-build-sycl.bat | 33 - .../examples/sycl/win-run-llama2.bat | 9 - .../examples/tokenize/CMakeLists.txt | 5 - .../llama.cpp/examples/tokenize/tokenize.cpp | 406 - .../llama.cpp/examples/ts-type-to-grammar.sh | 28 - ollama/llm/llama.cpp/flake.lock | 58 - ollama/llm/llama.cpp/flake.nix | 182 - ollama/llm/llama.cpp/ggml/.gitignore | 2 - ollama/llm/llama.cpp/ggml/CMakeLists.txt | 254 - .../llm/llama.cpp/ggml/cmake/FindSIMD.cmake | 100 - .../llm/llama.cpp/ggml/include/ggml-alloc.h | 76 - .../llm/llama.cpp/ggml/include/ggml-backend.h | 238 - ollama/llm/llama.cpp/ggml/include/ggml-blas.h | 23 - ollama/llm/llama.cpp/ggml/include/ggml-cann.h | 125 - ollama/llm/llama.cpp/ggml/include/ggml-cuda.h | 47 - .../llm/llama.cpp/ggml/include/ggml-kompute.h | 46 - .../llm/llama.cpp/ggml/include/ggml-metal.h | 65 - ollama/llm/llama.cpp/ggml/include/ggml-rpc.h | 24 - ollama/llm/llama.cpp/ggml/include/ggml-sycl.h | 42 - .../llm/llama.cpp/ggml/include/ggml-vulkan.h | 29 - ollama/llm/llama.cpp/ggml/include/ggml.h | 2455 -- ollama/llm/llama.cpp/ggml/src/CMakeLists.txt | 1325 - ollama/llm/llama.cpp/ggml/src/ggml-aarch64.c | 2193 -- ollama/llm/llama.cpp/ggml/src/ggml-aarch64.h | 39 - ollama/llm/llama.cpp/ggml/src/ggml-alloc.c | 1036 - .../llama.cpp/ggml/src/ggml-backend-impl.h | 153 - ollama/llm/llama.cpp/ggml/src/ggml-backend.c | 2240 -- ollama/llm/llama.cpp/ggml/src/ggml-blas.cpp | 367 - ollama/llm/llama.cpp/ggml/src/ggml-cann.cpp | 2020 -- .../ggml/src/ggml-cann/.clang-format | 168 - .../llm/llama.cpp/ggml/src/ggml-cann/Doxyfile | 2579 -- .../ggml/src/ggml-cann/acl_tensor.cpp | 175 - .../llama.cpp/ggml/src/ggml-cann/acl_tensor.h | 258 - .../ggml/src/ggml-cann/aclnn_ops.cpp | 3082 -- .../llama.cpp/ggml/src/ggml-cann/aclnn_ops.h | 592 - .../llm/llama.cpp/ggml/src/ggml-cann/common.h | 282 - .../ggml/src/ggml-cann/kernels/CMakeLists.txt | 33 - .../src/ggml-cann/kernels/ascendc_kernels.h | 19 - .../ggml/src/ggml-cann/kernels/dup.cpp | 223 - .../src/ggml-cann/kernels/get_row_f16.cpp | 186 - .../src/ggml-cann/kernels/get_row_f32.cpp | 180 - .../src/ggml-cann/kernels/get_row_q4_0.cpp | 193 - .../src/ggml-cann/kernels/get_row_q8_0.cpp | 191 - .../ggml-cann/kernels/quantize_f16_q8_0.cpp | 208 - .../ggml-cann/kernels/quantize_f32_q8_0.cpp | 206 - .../kernels/quantize_float_to_q4_0.cpp | 278 - ollama/llm/llama.cpp/ggml/src/ggml-common.h | 1833 -- ollama/llm/llama.cpp/ggml/src/ggml-cuda.cu | 3095 -- .../llm/llama.cpp/ggml/src/ggml-cuda/acc.cu | 47 - .../llm/llama.cpp/ggml/src/ggml-cuda/acc.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/arange.cu | 34 - .../llama.cpp/ggml/src/ggml-cuda/arange.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/argsort.cu | 104 - .../llama.cpp/ggml/src/ggml-cuda/argsort.cuh | 3 - .../llama.cpp/ggml/src/ggml-cuda/binbcast.cu | 280 - .../llama.cpp/ggml/src/ggml-cuda/binbcast.cuh | 6 - .../llm/llama.cpp/ggml/src/ggml-cuda/clamp.cu | 34 - .../llama.cpp/ggml/src/ggml-cuda/clamp.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/common.cuh | 669 - .../llama.cpp/ggml/src/ggml-cuda/concat.cu | 196 - .../llama.cpp/ggml/src/ggml-cuda/concat.cuh | 5 - .../ggml/src/ggml-cuda/conv-transpose-1d.cu | 87 - .../ggml/src/ggml-cuda/conv-transpose-1d.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/convert.cu | 686 - .../llama.cpp/ggml/src/ggml-cuda/convert.cuh | 13 - .../llm/llama.cpp/ggml/src/ggml-cuda/cpy.cu | 489 - .../llm/llama.cpp/ggml/src/ggml-cuda/cpy.cuh | 9 - .../ggml/src/ggml-cuda/dequantize.cuh | 103 - .../llama.cpp/ggml/src/ggml-cuda/diagmask.cu | 40 - .../llama.cpp/ggml/src/ggml-cuda/diagmask.cuh | 5 - .../llm/llama.cpp/ggml/src/ggml-cuda/dmmv.cu | 683 - .../llm/llama.cpp/ggml/src/ggml-cuda/dmmv.cuh | 20 - .../ggml/src/ggml-cuda/fattn-common.cuh | 701 - .../ggml/src/ggml-cuda/fattn-tile-f16.cu | 319 - .../ggml/src/ggml-cuda/fattn-tile-f16.cuh | 3 - .../ggml/src/ggml-cuda/fattn-tile-f32.cu | 312 - .../ggml/src/ggml-cuda/fattn-tile-f32.cuh | 3 - .../ggml/src/ggml-cuda/fattn-vec-f16.cuh | 397 - .../ggml/src/ggml-cuda/fattn-vec-f32.cuh | 374 - .../ggml/src/ggml-cuda/fattn-wmma-f16.cuh | 490 - .../llm/llama.cpp/ggml/src/ggml-cuda/fattn.cu | 345 - .../llama.cpp/ggml/src/ggml-cuda/fattn.cuh | 3 - .../llama.cpp/ggml/src/ggml-cuda/getrows.cu | 177 - .../llama.cpp/ggml/src/ggml-cuda/getrows.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/im2col.cu | 104 - .../llama.cpp/ggml/src/ggml-cuda/im2col.cuh | 5 - .../llm/llama.cpp/ggml/src/ggml-cuda/mma.cuh | 221 - .../llm/llama.cpp/ggml/src/ggml-cuda/mmq.cu | 150 - .../llm/llama.cpp/ggml/src/ggml-cuda/mmq.cuh | 2936 -- .../llm/llama.cpp/ggml/src/ggml-cuda/mmvq.cu | 425 - .../llm/llama.cpp/ggml/src/ggml-cuda/mmvq.cuh | 9 - .../llm/llama.cpp/ggml/src/ggml-cuda/norm.cu | 224 - .../llm/llama.cpp/ggml/src/ggml-cuda/norm.cuh | 7 - .../llm/llama.cpp/ggml/src/ggml-cuda/pad.cu | 49 - .../llm/llama.cpp/ggml/src/ggml-cuda/pad.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/pool2d.cu | 94 - .../llama.cpp/ggml/src/ggml-cuda/pool2d.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/quantize.cu | 169 - .../llama.cpp/ggml/src/ggml-cuda/quantize.cuh | 24 - .../llm/llama.cpp/ggml/src/ggml-cuda/rope.cu | 271 - .../llm/llama.cpp/ggml/src/ggml-cuda/rope.cuh | 5 - .../llm/llama.cpp/ggml/src/ggml-cuda/scale.cu | 31 - .../llama.cpp/ggml/src/ggml-cuda/scale.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/softmax.cu | 206 - .../llama.cpp/ggml/src/ggml-cuda/softmax.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/sumrows.cu | 40 - .../llama.cpp/ggml/src/ggml-cuda/sumrows.cuh | 3 - .../fattn-vec-f16-instance-hs128-f16-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-f16-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-f16-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-f16-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-f16-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-f16-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_0-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q4_1-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_0-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q5_1-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-f16.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs128-q8_0-q8_0.cu | 5 - .../fattn-vec-f16-instance-hs256-f16-f16.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-f16.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-q4_0.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-q4_1.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-q5_0.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-q5_1.cu | 5 - .../fattn-vec-f16-instance-hs64-f16-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-f16-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_0-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q4_1-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_0-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q5_1-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-f16.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs128-q8_0-q8_0.cu | 5 - .../fattn-vec-f32-instance-hs256-f16-f16.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-f16.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-q4_0.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-q4_1.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-q5_0.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-q5_1.cu | 5 - .../fattn-vec-f32-instance-hs64-f16-q8_0.cu | 5 - .../fattn-wmma-f16-instance-kqfloat-cpb16.cu | 10 - .../fattn-wmma-f16-instance-kqfloat-cpb32.cu | 9 - .../fattn-wmma-f16-instance-kqhalf-cpb16.cu | 10 - .../fattn-wmma-f16-instance-kqhalf-cpb32.cu | 10 - .../fattn-wmma-f16-instance-kqhalf-cpb8.cu | 8 - .../template-instances/generate_cu_files.py | 77 - .../template-instances/mmq-instance-iq1_s.cu | 5 - .../template-instances/mmq-instance-iq2_s.cu | 5 - .../template-instances/mmq-instance-iq2_xs.cu | 5 - .../mmq-instance-iq2_xxs.cu | 5 - .../template-instances/mmq-instance-iq3_s.cu | 5 - .../mmq-instance-iq3_xxs.cu | 5 - .../template-instances/mmq-instance-iq4_nl.cu | 5 - .../template-instances/mmq-instance-iq4_xs.cu | 5 - .../template-instances/mmq-instance-q2_k.cu | 5 - .../template-instances/mmq-instance-q3_k.cu | 5 - .../template-instances/mmq-instance-q4_0.cu | 5 - .../template-instances/mmq-instance-q4_1.cu | 5 - .../template-instances/mmq-instance-q4_k.cu | 5 - .../template-instances/mmq-instance-q5_0.cu | 5 - .../template-instances/mmq-instance-q5_1.cu | 5 - .../template-instances/mmq-instance-q5_k.cu | 5 - .../template-instances/mmq-instance-q6_k.cu | 5 - .../template-instances/mmq-instance-q8_0.cu | 5 - .../llama.cpp/ggml/src/ggml-cuda/tsembd.cu | 47 - .../llama.cpp/ggml/src/ggml-cuda/tsembd.cuh | 5 - .../llm/llama.cpp/ggml/src/ggml-cuda/unary.cu | 314 - .../llama.cpp/ggml/src/ggml-cuda/unary.cuh | 33 - .../llama.cpp/ggml/src/ggml-cuda/upscale.cu | 51 - .../llama.cpp/ggml/src/ggml-cuda/upscale.cuh | 5 - .../llama.cpp/ggml/src/ggml-cuda/vecdotq.cuh | 1133 - .../ggml/src/ggml-cuda/vendors/cuda.h | 14 - .../ggml/src/ggml-cuda/vendors/hip.h | 177 - .../ggml/src/ggml-cuda/vendors/musa.h | 171 - ollama/llm/llama.cpp/ggml/src/ggml-impl.h | 753 - .../llm/llama.cpp/ggml/src/ggml-kompute.cpp | 2038 -- ollama/llm/llama.cpp/ggml/src/ggml-metal.m | 3267 -- ollama/llm/llama.cpp/ggml/src/ggml-quants.c | 14872 ---------- ollama/llm/llama.cpp/ggml/src/ggml-quants.h | 136 - ollama/llm/llama.cpp/ggml/src/ggml-rpc.cpp | 1178 - ollama/llm/llama.cpp/ggml/src/ggml-sycl.cpp | 5330 ---- .../llama.cpp/ggml/src/ggml-sycl/backend.hpp | 29 - .../llama.cpp/ggml/src/ggml-sycl/common.cpp | 53 - .../llama.cpp/ggml/src/ggml-sycl/common.hpp | 355 - .../llama.cpp/ggml/src/ggml-sycl/concat.cpp | 195 - .../llama.cpp/ggml/src/ggml-sycl/concat.hpp | 21 - .../llm/llama.cpp/ggml/src/ggml-sycl/conv.cpp | 99 - .../llm/llama.cpp/ggml/src/ggml-sycl/conv.hpp | 21 - .../llama.cpp/ggml/src/ggml-sycl/convert.cpp | 547 - .../llama.cpp/ggml/src/ggml-sycl/convert.hpp | 27 - .../ggml/src/ggml-sycl/dequantize.hpp | 698 - .../llm/llama.cpp/ggml/src/ggml-sycl/dmmv.cpp | 1023 - .../llm/llama.cpp/ggml/src/ggml-sycl/dmmv.hpp | 27 - .../ggml/src/ggml-sycl/dpct/helper.hpp | 3011 -- .../llm/llama.cpp/ggml/src/ggml-sycl/mmq.cpp | 3031 -- .../llm/llama.cpp/ggml/src/ggml-sycl/mmq.hpp | 33 - .../llm/llama.cpp/ggml/src/ggml-sycl/mmvq.cpp | 1027 - .../llm/llama.cpp/ggml/src/ggml-sycl/mmvq.hpp | 27 - .../llm/llama.cpp/ggml/src/ggml-sycl/norm.cpp | 377 - .../llm/llama.cpp/ggml/src/ggml-sycl/norm.hpp | 35 - .../llama.cpp/ggml/src/ggml-sycl/presets.hpp | 68 - .../llm/llama.cpp/ggml/src/ggml-sycl/rope.cpp | 275 - .../llm/llama.cpp/ggml/src/ggml-sycl/rope.hpp | 22 - .../llama.cpp/ggml/src/ggml-sycl/softmax.cpp | 251 - .../llama.cpp/ggml/src/ggml-sycl/softmax.hpp | 24 - .../llama.cpp/ggml/src/ggml-sycl/tsembd.cpp | 71 - .../llama.cpp/ggml/src/ggml-sycl/tsembd.hpp | 21 - .../llama.cpp/ggml/src/ggml-sycl/vecdotq.hpp | 1140 - ollama/llm/llama.cpp/ggml/src/ggml-vulkan.cpp | 7392 ----- ollama/llm/llama.cpp/ggml/src/ggml.c | 22120 -------------- .../ggml/src/kompute-shaders/common.comp | 102 - .../ggml/src/kompute-shaders/op_add.comp | 58 - .../ggml/src/kompute-shaders/op_addrow.comp | 25 - .../src/kompute-shaders/op_cpy_f16_f16.comp | 52 - .../src/kompute-shaders/op_cpy_f16_f32.comp | 52 - .../src/kompute-shaders/op_cpy_f32_f16.comp | 52 - .../src/kompute-shaders/op_cpy_f32_f32.comp | 52 - .../ggml/src/kompute-shaders/op_diagmask.comp | 30 - .../ggml/src/kompute-shaders/op_gelu.comp | 22 - .../ggml/src/kompute-shaders/op_getrows.comp | 17 - .../src/kompute-shaders/op_getrows_f16.comp | 31 - .../src/kompute-shaders/op_getrows_f32.comp | 31 - .../src/kompute-shaders/op_getrows_q4_0.comp | 38 - .../src/kompute-shaders/op_getrows_q4_1.comp | 39 - .../src/kompute-shaders/op_getrows_q6_k.comp | 44 - .../ggml/src/kompute-shaders/op_mul.comp | 52 - .../src/kompute-shaders/op_mul_mat_f16.comp | 67 - .../kompute-shaders/op_mul_mat_mat_f32.comp | 51 - .../src/kompute-shaders/op_mul_mat_q4_0.comp | 33 - .../src/kompute-shaders/op_mul_mat_q4_1.comp | 35 - .../src/kompute-shaders/op_mul_mat_q6_k.comp | 94 - .../src/kompute-shaders/op_mul_mat_q8_0.comp | 73 - .../src/kompute-shaders/op_mul_mv_q_n.comp | 48 - .../kompute-shaders/op_mul_mv_q_n_pre.comp | 22 - .../ggml/src/kompute-shaders/op_norm.comp | 84 - .../ggml/src/kompute-shaders/op_relu.comp | 21 - .../ggml/src/kompute-shaders/op_rmsnorm.comp | 53 - .../ggml/src/kompute-shaders/op_rope_f16.comp | 73 - .../ggml/src/kompute-shaders/op_rope_f32.comp | 73 - .../ggml/src/kompute-shaders/op_scale.comp | 19 - .../ggml/src/kompute-shaders/op_scale_8.comp | 23 - .../ggml/src/kompute-shaders/op_silu.comp | 22 - .../ggml/src/kompute-shaders/op_softmax.comp | 56 - .../ggml/src/kompute-shaders/rope_common.comp | 67 - .../llama.cpp/ggml/src/llamafile/sgemm.cpp | 1027 - .../llm/llama.cpp/ggml/src/llamafile/sgemm.h | 14 - .../ggml/src/vulkan-shaders/CMakeLists.txt | 7 - .../ggml/src/vulkan-shaders/add.comp | 14 - .../ggml/src/vulkan-shaders/argsort.comp | 71 - .../ggml/src/vulkan-shaders/clamp.comp | 15 - .../ggml/src/vulkan-shaders/concat.comp | 35 - .../ggml/src/vulkan-shaders/copy.comp | 18 - .../ggml/src/vulkan-shaders/dequant_f32.comp | 20 - .../src/vulkan-shaders/dequant_funcs.comp | 68 - .../ggml/src/vulkan-shaders/dequant_head.comp | 13 - .../src/vulkan-shaders/dequant_iq4_nl.comp | 30 - .../ggml/src/vulkan-shaders/dequant_q2_k.comp | 34 - .../ggml/src/vulkan-shaders/dequant_q3_k.comp | 42 - .../ggml/src/vulkan-shaders/dequant_q4_0.comp | 30 - .../ggml/src/vulkan-shaders/dequant_q4_1.comp | 32 - .../ggml/src/vulkan-shaders/dequant_q4_k.comp | 56 - .../ggml/src/vulkan-shaders/dequant_q5_0.comp | 34 - .../ggml/src/vulkan-shaders/dequant_q5_1.comp | 35 - .../ggml/src/vulkan-shaders/dequant_q5_k.comp | 58 - .../ggml/src/vulkan-shaders/dequant_q6_k.comp | 33 - .../ggml/src/vulkan-shaders/dequant_q8_0.comp | 31 - .../src/vulkan-shaders/diag_mask_inf.comp | 34 - .../ggml/src/vulkan-shaders/div.comp | 14 - .../ggml/src/vulkan-shaders/gelu.comp | 25 - .../ggml/src/vulkan-shaders/gelu_quick.comp | 23 - .../vulkan-shaders/generic_binary_head.comp | 52 - .../ggml/src/vulkan-shaders/generic_head.comp | 9 - .../vulkan-shaders/generic_unary_head.comp | 39 - .../ggml/src/vulkan-shaders/get_rows.comp | 26 - .../src/vulkan-shaders/get_rows_quant.comp | 31 - .../ggml/src/vulkan-shaders/group_norm.comp | 66 - .../ggml/src/vulkan-shaders/im2col.comp | 57 - .../ggml/src/vulkan-shaders/leaky_relu.comp | 22 - .../ggml/src/vulkan-shaders/mul.comp | 14 - .../mul_mat_split_k_reduce.comp | 29 - .../ggml/src/vulkan-shaders/mul_mat_vec.comp | 57 - .../src/vulkan-shaders/mul_mat_vec_base.comp | 81 - .../src/vulkan-shaders/mul_mat_vec_nc.comp | 71 - .../src/vulkan-shaders/mul_mat_vec_p021.comp | 73 - .../src/vulkan-shaders/mul_mat_vec_q2_k.comp | 73 - .../src/vulkan-shaders/mul_mat_vec_q3_k.comp | 66 - .../src/vulkan-shaders/mul_mat_vec_q4_k.comp | 115 - .../src/vulkan-shaders/mul_mat_vec_q5_k.comp | 111 - .../src/vulkan-shaders/mul_mat_vec_q6_k.comp | 79 - .../ggml/src/vulkan-shaders/mul_mm.comp | 507 - .../ggml/src/vulkan-shaders/norm.comp | 44 - .../ggml/src/vulkan-shaders/pad.comp | 26 - .../ggml/src/vulkan-shaders/relu.comp | 21 - .../ggml/src/vulkan-shaders/rms_norm.comp | 42 - .../ggml/src/vulkan-shaders/rope_head.comp | 44 - .../ggml/src/vulkan-shaders/rope_neox.comp | 37 - .../ggml/src/vulkan-shaders/rope_norm.comp | 37 - .../ggml/src/vulkan-shaders/scale.comp | 14 - .../ggml/src/vulkan-shaders/silu.comp | 22 - .../ggml/src/vulkan-shaders/soft_max.comp | 106 - .../ggml/src/vulkan-shaders/square.comp | 15 - .../ggml/src/vulkan-shaders/sum_rows.comp | 37 - .../ggml/src/vulkan-shaders/tanh.comp | 21 - .../vulkan-shaders/timestep_embedding.comp | 41 - .../ggml/src/vulkan-shaders/types.comp | 200 - .../ggml/src/vulkan-shaders/upscale.comp | 36 - .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 579 - ollama/llm/llama.cpp/gguf-py/LICENSE | 21 - ollama/llm/llama.cpp/gguf-py/README.md | 90 - .../llm/llama.cpp/gguf-py/examples/reader.py | 47 - .../llm/llama.cpp/gguf-py/examples/writer.py | 40 - ollama/llm/llama.cpp/gguf-py/gguf/__init__.py | 9 - .../llm/llama.cpp/gguf-py/gguf/constants.py | 1331 - ollama/llm/llama.cpp/gguf-py/gguf/gguf.py | 15 - .../llm/llama.cpp/gguf-py/gguf/gguf_reader.py | 317 - .../llm/llama.cpp/gguf-py/gguf/gguf_writer.py | 885 - ollama/llm/llama.cpp/gguf-py/gguf/lazy.py | 211 - ollama/llm/llama.cpp/gguf-py/gguf/metadata.py | 510 - ollama/llm/llama.cpp/gguf-py/gguf/py.typed | 0 ollama/llm/llama.cpp/gguf-py/gguf/quants.py | 121 - .../llama.cpp/gguf-py/gguf/tensor_mapping.py | 649 - ollama/llm/llama.cpp/gguf-py/gguf/utility.py | 69 - ollama/llm/llama.cpp/gguf-py/gguf/vocab.py | 465 - ollama/llm/llama.cpp/gguf-py/pyproject.toml | 38 - .../llm/llama.cpp/gguf-py/scripts/__init__.py | 6 - .../gguf-py/scripts/gguf_convert_endian.py | 134 - .../llama.cpp/gguf-py/scripts/gguf_dump.py | 454 - .../llama.cpp/gguf-py/scripts/gguf_hash.py | 102 - .../gguf-py/scripts/gguf_new_metadata.py | 244 - .../gguf-py/scripts/gguf_set_metadata.py | 95 - .../llm/llama.cpp/gguf-py/tests/__init__.py | 1 - .../llama.cpp/gguf-py/tests/test_metadata.py | 203 - ollama/llm/llama.cpp/grammars/README.md | 382 - ollama/llm/llama.cpp/grammars/arithmetic.gbnf | 6 - ollama/llm/llama.cpp/grammars/c.gbnf | 42 - ollama/llm/llama.cpp/grammars/chess.gbnf | 13 - ollama/llm/llama.cpp/grammars/japanese.gbnf | 7 - ollama/llm/llama.cpp/grammars/json.gbnf | 25 - ollama/llm/llama.cpp/grammars/json_arr.gbnf | 34 - ollama/llm/llama.cpp/grammars/list.gbnf | 4 - ollama/llm/llama.cpp/include/llama.h | 1240 - ollama/llm/llama.cpp/media/llama-leader.jpeg | Bin 199945 -> 0 bytes ollama/llm/llama.cpp/media/llama0-banner.png | Bin 144615 -> 0 bytes ollama/llm/llama.cpp/media/llama0-logo.png | Bin 179940 -> 0 bytes ollama/llm/llama.cpp/media/llama1-banner.png | Bin 33331 -> 0 bytes ollama/llm/llama.cpp/media/llama1-logo.png | Bin 32494 -> 0 bytes ollama/llm/llama.cpp/media/matmul.png | Bin 265705 -> 0 bytes ollama/llm/llama.cpp/media/matmul.svg | 1238 - ollama/llm/llama.cpp/models/.editorconfig | 1 - .../llama.cpp/models/ggml-vocab-aquila.gguf | Bin 4825676 -> 0 bytes .../llama.cpp/models/ggml-vocab-baichuan.gguf | Bin 1340998 -> 0 bytes .../llama.cpp/models/ggml-vocab-bert-bge.gguf | Bin 627549 -> 0 bytes .../models/ggml-vocab-bert-bge.gguf.inp | 112 - .../models/ggml-vocab-bert-bge.gguf.out | 46 - .../models/ggml-vocab-command-r.gguf | Bin 10874545 -> 0 bytes .../models/ggml-vocab-command-r.gguf.inp | 112 - .../models/ggml-vocab-command-r.gguf.out | 46 - .../models/ggml-vocab-deepseek-coder.gguf | Bin 1156067 -> 0 bytes .../models/ggml-vocab-deepseek-coder.gguf.inp | 112 - .../models/ggml-vocab-deepseek-coder.gguf.out | 46 - .../models/ggml-vocab-deepseek-llm.gguf | Bin 3970167 -> 0 bytes .../models/ggml-vocab-deepseek-llm.gguf.inp | 112 - .../models/ggml-vocab-deepseek-llm.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-falcon.gguf | Bin 2287728 -> 0 bytes .../models/ggml-vocab-falcon.gguf.inp | 112 - .../models/ggml-vocab-falcon.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-gpt-2.gguf | Bin 1766807 -> 0 bytes .../models/ggml-vocab-gpt-2.gguf.inp | 112 - .../models/ggml-vocab-gpt-2.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-gpt-neox.gguf | Bin 1771431 -> 0 bytes .../models/ggml-vocab-llama-bpe.gguf | Bin 7818140 -> 0 bytes .../models/ggml-vocab-llama-bpe.gguf.inp | 112 - .../models/ggml-vocab-llama-bpe.gguf.out | 46 - .../models/ggml-vocab-llama-spm.gguf | Bin 723869 -> 0 bytes .../models/ggml-vocab-llama-spm.gguf.inp | 112 - .../models/ggml-vocab-llama-spm.gguf.out | 46 - .../llm/llama.cpp/models/ggml-vocab-mpt.gguf | Bin 1771393 -> 0 bytes .../llama.cpp/models/ggml-vocab-mpt.gguf.inp | 112 - .../llama.cpp/models/ggml-vocab-mpt.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-phi-3.gguf | Bin 726019 -> 0 bytes .../models/ggml-vocab-phi-3.gguf.inp | 112 - .../models/ggml-vocab-phi-3.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-qwen2.gguf | Bin 5928681 -> 0 bytes .../models/ggml-vocab-qwen2.gguf.inp | 112 - .../models/ggml-vocab-qwen2.gguf.out | 46 - .../llama.cpp/models/ggml-vocab-refact.gguf | Bin 1720710 -> 0 bytes .../models/ggml-vocab-refact.gguf.inp | 112 - .../models/ggml-vocab-refact.gguf.out | 46 - .../models/ggml-vocab-starcoder.gguf | Bin 1719346 -> 0 bytes .../models/ggml-vocab-starcoder.gguf.inp | 112 - .../models/ggml-vocab-starcoder.gguf.out | 46 - ollama/llm/llama.cpp/mypy.ini | 7 - ollama/llm/llama.cpp/pocs/CMakeLists.txt | 12 - ollama/llm/llama.cpp/pocs/vdot/CMakeLists.txt | 9 - ollama/llm/llama.cpp/pocs/vdot/q8dot.cpp | 172 - ollama/llm/llama.cpp/pocs/vdot/vdot.cpp | 310 - ollama/llm/llama.cpp/poetry.lock | 1197 - .../llm/llama.cpp/prompts/LLM-questions.txt | 49 - ollama/llm/llama.cpp/prompts/alpaca.txt | 1 - ollama/llm/llama.cpp/prompts/assistant.txt | 31 - .../llama.cpp/prompts/chat-with-baichuan.txt | 4 - .../llm/llama.cpp/prompts/chat-with-bob.txt | 7 - .../llm/llama.cpp/prompts/chat-with-qwen.txt | 1 - .../llama.cpp/prompts/chat-with-vicuna-v0.txt | 7 - .../llama.cpp/prompts/chat-with-vicuna-v1.txt | 7 - ollama/llm/llama.cpp/prompts/chat.txt | 28 - ollama/llm/llama.cpp/prompts/dan-modified.txt | 1 - ollama/llm/llama.cpp/prompts/dan.txt | 1 - ollama/llm/llama.cpp/prompts/mnemonics.txt | 93 - .../llama.cpp/prompts/parallel-questions.txt | 43 - ollama/llm/llama.cpp/prompts/reason-act.txt | 18 - ollama/llm/llama.cpp/pyproject.toml | 44 - ollama/llm/llama.cpp/pyrightconfig.json | 21 - ollama/llm/llama.cpp/requirements.txt | 12 - .../requirements/requirements-all.txt | 12 - .../requirements-compare-llama-bench.txt | 2 - .../requirements-convert_hf_to_gguf.txt | 3 - ...requirements-convert_hf_to_gguf_update.txt | 3 - .../requirements-convert_legacy_llama.txt | 5 - ...equirements-convert_llama_ggml_to_gguf.txt | 1 - .../requirements-convert_lora_to_gguf.txt | 2 - .../requirements/requirements-pydantic.txt | 3 - .../requirements-test-tokenizer-random.txt | 1 - ollama/llm/llama.cpp/scripts/build-info.sh | 30 - .../llama.cpp/scripts/check-requirements.sh | 179 - ollama/llm/llama.cpp/scripts/ci-run.sh | 50 - .../llm/llama.cpp/scripts/compare-commits.sh | 27 - .../llama.cpp/scripts/compare-llama-bench.py | 376 - ollama/llm/llama.cpp/scripts/debug-test.sh | 203 - ollama/llm/llama.cpp/scripts/gen-authors.sh | 9 - .../llm/llama.cpp/scripts/gen-unicode-data.py | 196 - ollama/llm/llama.cpp/scripts/get-flags.mk | 38 - ollama/llm/llama.cpp/scripts/get-hellaswag.sh | 10 - ollama/llm/llama.cpp/scripts/get-pg.sh | 70 - .../llm/llama.cpp/scripts/get-wikitext-103.sh | 10 - .../llm/llama.cpp/scripts/get-wikitext-2.sh | 11 - .../llm/llama.cpp/scripts/get-winogrande.sh | 10 - ollama/llm/llama.cpp/scripts/hf.sh | 112 - .../llm/llama.cpp/scripts/install-oneapi.bat | 19 - ollama/llm/llama.cpp/scripts/pod-llama.sh | 212 - ollama/llm/llama.cpp/scripts/qnt-all.sh | 30 - ollama/llm/llama.cpp/scripts/run-all-perf.sh | 34 - ollama/llm/llama.cpp/scripts/run-all-ppl.sh | 30 - .../llm/llama.cpp/scripts/run-with-preset.py | 146 - ollama/llm/llama.cpp/scripts/server-llm.sh | 418 - ollama/llm/llama.cpp/scripts/sync-ggml-am.sh | 198 - ollama/llm/llama.cpp/scripts/sync-ggml.last | 1 - ollama/llm/llama.cpp/scripts/sync-ggml.sh | 46 - .../scripts/verify-checksum-models.py | 84 - ollama/llm/llama.cpp/scripts/xxd.cmake | 16 - ollama/llm/llama.cpp/spm-headers/ggml-alloc.h | 76 - .../llm/llama.cpp/spm-headers/ggml-backend.h | 238 - ollama/llm/llama.cpp/spm-headers/ggml-metal.h | 65 - ollama/llm/llama.cpp/spm-headers/ggml.h | 2455 -- ollama/llm/llama.cpp/spm-headers/llama.h | 1240 - ollama/llm/llama.cpp/src/CMakeLists.txt | 33 - ollama/llm/llama.cpp/src/llama-grammar.cpp | 539 - ollama/llm/llama.cpp/src/llama-grammar.h | 39 - ollama/llm/llama.cpp/src/llama-impl.h | 26 - ollama/llm/llama.cpp/src/llama-sampling.cpp | 635 - ollama/llm/llama.cpp/src/llama-sampling.h | 56 - ollama/llm/llama.cpp/src/llama-vocab.cpp | 1729 -- ollama/llm/llama.cpp/src/llama-vocab.h | 132 - ollama/llm/llama.cpp/src/llama.cpp | 19173 ------------ ollama/llm/llama.cpp/src/unicode-data.cpp | 7032 ----- ollama/llm/llama.cpp/src/unicode-data.h | 20 - ollama/llm/llama.cpp/src/unicode.cpp | 818 - ollama/llm/llama.cpp/src/unicode.h | 67 - ollama/llm/llama.cpp/tests/.gitignore | 4 - ollama/llm/llama.cpp/tests/CMakeLists.txt | 137 - ollama/llm/llama.cpp/tests/get-model.cpp | 21 - ollama/llm/llama.cpp/tests/get-model.h | 2 - .../tests/run-json-schema-to-grammar.mjs | 10 - .../llm/llama.cpp/tests/test-autorelease.cpp | 24 - .../llm/llama.cpp/tests/test-backend-ops.cpp | 2564 -- ollama/llm/llama.cpp/tests/test-c.c | 7 - .../llama.cpp/tests/test-chat-template.cpp | 177 - .../llm/llama.cpp/tests/test-double-float.cpp | 57 - ollama/llm/llama.cpp/tests/test-grad0.cpp | 1566 - .../tests/test-grammar-integration.cpp | 1325 - .../llama.cpp/tests/test-grammar-parser.cpp | 515 - .../tests/test-json-schema-to-grammar.cpp | 1273 - .../llama.cpp/tests/test-llama-grammar.cpp | 408 - .../tests/test-model-load-cancel.cpp | 27 - ollama/llm/llama.cpp/tests/test-opt.cpp | 181 - .../llm/llama.cpp/tests/test-quantize-fns.cpp | 185 - .../llama.cpp/tests/test-quantize-perf.cpp | 363 - ollama/llm/llama.cpp/tests/test-rope.cpp | 220 - ollama/llm/llama.cpp/tests/test-sampling.cpp | 301 - .../llm/llama.cpp/tests/test-tokenizer-0.cpp | 292 - .../llm/llama.cpp/tests/test-tokenizer-0.py | 46 - .../llm/llama.cpp/tests/test-tokenizer-0.sh | 41 - .../llama.cpp/tests/test-tokenizer-1-bpe.cpp | 152 - .../llama.cpp/tests/test-tokenizer-1-spm.cpp | 122 - .../llama.cpp/tests/test-tokenizer-random.py | 566 - ollama/llm/llm.go | 41 - ollama/llm/llm_darwin_amd64.go | 11 - ollama/llm/llm_darwin_arm64.go | 11 - ollama/llm/llm_linux.go | 11 - ollama/llm/llm_windows.go | 20 - ollama/llm/memory.go | 355 - ollama/llm/memory_test.go | 129 - ollama/llm/patches/01-load-progress.diff | 31 - ollama/llm/patches/02-clip-log.diff | 12 - ollama/llm/patches/03-load_exception.diff | 45 - ollama/llm/patches/04-metal.diff | 45 - .../llm/patches/05-default-pretokenizer.diff | 32 - ollama/llm/patches/06-embeddings.diff | 45 - ollama/llm/patches/07-clip-unicode.diff | 42 - ollama/llm/patches/08-pooling.diff | 60 - ollama/llm/patches/09-lora.diff | 350 - .../llm/patches/11-phi3-sliding-window.diff | 43 - ollama/llm/payload.go | 233 - ollama/llm/server.go | 1090 - ollama/llm/status.go | 44 - ollama/macapp/.eslintrc.json | 16 - ollama/macapp/.gitignore | 92 - ollama/macapp/README.md | 21 - ollama/macapp/assets/icon.icns | Bin 239658 -> 0 bytes ollama/macapp/assets/iconDarkTemplate.png | Bin 402 -> 0 bytes ollama/macapp/assets/iconDarkTemplate@2x.png | Bin 741 -> 0 bytes .../macapp/assets/iconDarkUpdateTemplate.png | Bin 440 -> 0 bytes .../assets/iconDarkUpdateTemplate@2x.png | Bin 763 -> 0 bytes ollama/macapp/assets/iconTemplate.png | Bin 447 -> 0 bytes ollama/macapp/assets/iconTemplate@2x.png | Bin 891 -> 0 bytes ollama/macapp/assets/iconUpdateTemplate.png | Bin 443 -> 0 bytes .../macapp/assets/iconUpdateTemplate@2x.png | Bin 844 -> 0 bytes ollama/macapp/forge.config.ts | 78 - ollama/macapp/package-lock.json | 16695 ----------- ollama/macapp/package.json | 84 - ollama/macapp/postcss.config.js | 7 - ollama/macapp/src/app.css | 34 - ollama/macapp/src/app.tsx | 122 - ollama/macapp/src/declarations.d.ts | 4 - ollama/macapp/src/index.html | 9 - ollama/macapp/src/index.ts | 302 - ollama/macapp/src/install.ts | 21 - ollama/macapp/src/ollama.svg | 9 - ollama/macapp/src/preload.ts | 0 ollama/macapp/src/renderer.tsx | 7 - ollama/macapp/tailwind.config.js | 6 - ollama/macapp/tsconfig.json | 20 - ollama/macapp/webpack.main.config.ts | 20 - ollama/macapp/webpack.plugins.ts | 14 - ollama/macapp/webpack.renderer.config.ts | 19 - ollama/macapp/webpack.rules.ts | 35 - ollama/main.go | 13 - ollama/openai/openai.go | 913 - ollama/openai/openai_test.go | 499 - ollama/parser/parser.go | 304 - ollama/parser/parser_test.go | 643 - ollama/progress/bar.go | 216 - ollama/progress/progress.go | 111 - ollama/progress/spinner.go | 73 - ollama/readline/buffer.go | 563 - ollama/readline/errors.go | 15 - ollama/readline/history.go | 157 - ollama/readline/readline.go | 287 - ollama/readline/readline_unix.go | 19 - ollama/readline/readline_windows.go | 6 - ollama/readline/term.go | 37 - ollama/readline/term_bsd.go | 25 - ollama/readline/term_linux.go | 30 - ollama/readline/term_windows.go | 38 - ollama/readline/types.go | 78 - ollama/scripts/build.sh | 21 - ollama/scripts/build_darwin.sh | 46 - ollama/scripts/build_docker.sh | 77 - ollama/scripts/build_linux.sh | 31 - ollama/scripts/build_remote.py | 76 - ollama/scripts/build_windows.ps1 | 160 - ollama/scripts/install.sh | 340 - ollama/scripts/publish.sh | 25 - ollama/scripts/push_docker.sh | 15 - ollama/scripts/rh_linux_deps.sh | 66 - ollama/scripts/tag_latest.sh | 33 - ollama/server/auth.go | 95 - ollama/server/download.go | 499 - ollama/server/fixblobs.go | 26 - ollama/server/fixblobs_test.go | 83 - ollama/server/images.go | 1203 - ollama/server/layer.go | 126 - ollama/server/manifest.go | 168 - ollama/server/manifest_test.go | 150 - ollama/server/model.go | 350 - ollama/server/model_test.go | 135 - ollama/server/modelpath.go | 148 - ollama/server/modelpath_test.go | 156 - ollama/server/prompt.go | 74 - ollama/server/prompt_test.go | 211 - ollama/server/routes.go | 1448 - ollama/server/routes_create_test.go | 618 - ollama/server/routes_delete_test.go | 111 - ollama/server/routes_generate_test.go | 714 - ollama/server/routes_list_test.go | 65 - ollama/server/routes_test.go | 524 - ollama/server/sched.go | 810 - ollama/server/sched_test.go | 748 - ollama/server/sparse_common.go | 8 - ollama/server/sparse_windows.go | 17 - .../testdata/tools/command-r-plus.gotmpl | 67 - .../server/testdata/tools/command-r-plus.out | 39 - .../server/testdata/tools/firefunction.gotmpl | 31 - ollama/server/testdata/tools/firefunction.out | 17 - .../tools/llama3-groq-tool-use.gotmpl | 43 - .../testdata/tools/llama3-groq-tool-use.out | 24 - ollama/server/testdata/tools/messages.json | 39 - ollama/server/testdata/tools/mistral.gotmpl | 15 - ollama/server/testdata/tools/mistral.out | 3 - ollama/server/testdata/tools/tools.json | 30 - ollama/server/testdata/tools/xlam.gotmpl | 45 - ollama/server/testdata/tools/xlam.out | 40 - ollama/server/upload.go | 401 - ollama/template/alfred.gotmpl | 1 - ollama/template/alfred.json | 8 - ollama/template/alpaca.gotmpl | 8 - ollama/template/alpaca.json | 6 - ollama/template/chatml.gotmpl | 6 - ollama/template/chatml.json | 6 - ollama/template/chatqa.gotmpl | 6 - ollama/template/chatqa.json | 8 - ollama/template/codellama-70b-instruct.gotmpl | 10 - ollama/template/codellama-70b-instruct.json | 7 - ollama/template/falcon-instruct.gotmpl | 5 - ollama/template/falcon-instruct.json | 6 - ollama/template/gemma-instruct.gotmpl | 5 - ollama/template/gemma-instruct.json | 6 - ollama/template/granite-instruct.gotmpl | 9 - ollama/template/granite-instruct.json | 7 - ollama/template/index.json | 138 - ollama/template/llama2-chat.gotmpl | 6 - ollama/template/llama2-chat.json | 8 - ollama/template/llama3-instruct.gotmpl | 7 - ollama/template/llama3-instruct.json | 7 - ollama/template/magicoder.gotmpl | 8 - ollama/template/magicoder.json | 6 - ollama/template/mistral-instruct.gotmpl | 3 - ollama/template/mistral-instruct.json | 6 - ollama/template/openchat.gotmpl | 1 - ollama/template/openchat.json | 5 - ollama/template/phi-3.gotmpl | 6 - ollama/template/phi-3.json | 8 - ollama/template/solar-instruct.gotmpl | 9 - ollama/template/solar-instruct.json | 7 - ollama/template/starcoder2-instruct.gotmpl | 8 - ollama/template/starcoder2-instruct.json | 7 - ollama/template/template.go | 447 - ollama/template/template_test.go | 417 - .../alfred.gotmpl/system-user-assistant-user | 1 - ollama/template/testdata/alfred.gotmpl/user | 1 - .../alfred.gotmpl/user-assistant-user | 1 - .../alpaca.gotmpl/system-user-assistant-user | 12 - ollama/template/testdata/alpaca.gotmpl/user | 4 - .../alpaca.gotmpl/user-assistant-user | 10 - .../chatml.gotmpl/system-user-assistant-user | 9 - ollama/template/testdata/chatml.gotmpl/user | 3 - .../chatml.gotmpl/user-assistant-user | 7 - .../chatqa.gotmpl/system-user-assistant-user | 9 - ollama/template/testdata/chatqa.gotmpl/user | 3 - .../chatqa.gotmpl/user-assistant-user | 7 - .../system-user-assistant-user | 12 - .../codellama-70b-instruct.gotmpl/user | 6 - .../user-assistant-user | 10 - .../system-user-assistant-user | 8 - .../testdata/falcon-instruct.gotmpl/user | 3 - .../user-assistant-user | 7 - .../system-user-assistant-user | 8 - .../testdata/gemma-instruct.gotmpl/user | 3 - .../gemma-instruct.gotmpl/user-assistant-user | 7 - .../system-user-assistant-user | 13 - .../testdata/granite-instruct.gotmpl/user | 4 - .../user-assistant-user | 10 - .../system-user-assistant-user | 7 - .../template/testdata/llama2-chat.gotmpl/user | 3 - .../llama2-chat.gotmpl/user-assistant-user | 5 - .../system-user-assistant-user | 10 - .../testdata/llama3-instruct.gotmpl/user | 4 - .../user-assistant-user | 8 - .../system-user-assistant-user | 12 - .../template/testdata/magicoder.gotmpl/user | 4 - .../magicoder.gotmpl/user-assistant-user | 10 - .../system-user-assistant-user | 3 - .../testdata/mistral-instruct.gotmpl/user | 1 - .../user-assistant-user | 1 - .../system-user-assistant-user | 1 - ollama/template/testdata/openchat.gotmpl/user | 1 - .../openchat.gotmpl/user-assistant-user | 1 - .../phi-3.gotmpl/system-user-assistant-user | 9 - ollama/template/testdata/phi-3.gotmpl/user | 3 - .../testdata/phi-3.gotmpl/user-assistant-user | 7 - .../system-user-assistant-user | 13 - .../testdata/solar-instruct.gotmpl/user | 4 - .../solar-instruct.gotmpl/user-assistant-user | 10 - .../system-user-assistant-user | 12 - .../testdata/starcoder2-instruct.gotmpl/user | 4 - .../user-assistant-user | 10 - ollama/template/testdata/templates.jsonl | 35 - .../vicuna.gotmpl/system-user-assistant-user | 6 - ollama/template/testdata/vicuna.gotmpl/user | 2 - .../vicuna.gotmpl/user-assistant-user | 4 - .../zephyr.gotmpl/system-user-assistant-user | 9 - ollama/template/testdata/zephyr.gotmpl/user | 3 - .../zephyr.gotmpl/user-assistant-user | 7 - ollama/template/vicuna.gotmpl | 4 - ollama/template/vicuna.json | 6 - ollama/template/zephyr.gotmpl | 6 - ollama/template/zephyr.json | 8 - ollama/types/errtypes/errtypes.go | 21 - ollama/types/model/name.go | 364 - ollama/types/model/name_test.go | 358 - .../testdata/fuzz/FuzzName/d37463aa416f6bab | 2 - ollama/util/bufioutil/buffer_seeker.go | 34 - ollama/util/bufioutil/buffer_seeker_test.go | 64 - ollama/version/version.go | 3 - 1401 files changed, 412247 deletions(-) delete mode 100755 ollama/.dockerignore delete mode 100755 ollama/.gitattributes delete mode 100755 ollama/.github/ISSUE_TEMPLATE/10_bug_report.yml delete mode 100755 ollama/.github/ISSUE_TEMPLATE/20_feature_request.md delete mode 100755 ollama/.github/ISSUE_TEMPLATE/30_model_request.md delete mode 100755 ollama/.github/ISSUE_TEMPLATE/config.yml delete mode 100755 ollama/.github/workflows/latest.yaml delete mode 100755 ollama/.github/workflows/release.yaml delete mode 100755 ollama/.github/workflows/test.yaml delete mode 100755 ollama/.gitignore delete mode 100755 ollama/.gitmodules delete mode 100755 ollama/.golangci.yaml delete mode 100755 ollama/.prettierrc.json delete mode 100755 ollama/Dockerfile delete mode 100755 ollama/LICENSE delete mode 100755 ollama/README.md delete mode 100755 ollama/SECURITY.md delete mode 100755 ollama/api/client.go delete mode 100755 ollama/api/client_test.go delete mode 100755 ollama/api/types.go delete mode 100755 ollama/api/types_test.go delete mode 100755 ollama/app/.gitignore delete mode 100755 ollama/app/README.md delete mode 100755 ollama/app/assets/app.ico delete mode 100755 ollama/app/assets/assets.go delete mode 100755 ollama/app/assets/setup.bmp delete mode 100755 ollama/app/assets/tray.ico delete mode 100755 ollama/app/assets/tray_upgrade.ico delete mode 100755 ollama/app/lifecycle/getstarted_nonwindows.go delete mode 100755 ollama/app/lifecycle/getstarted_windows.go delete mode 100755 ollama/app/lifecycle/lifecycle.go delete mode 100755 ollama/app/lifecycle/logging.go delete mode 100755 ollama/app/lifecycle/logging_nonwindows.go delete mode 100755 ollama/app/lifecycle/logging_test.go delete mode 100755 ollama/app/lifecycle/logging_windows.go delete mode 100755 ollama/app/lifecycle/paths.go delete mode 100755 ollama/app/lifecycle/server.go delete mode 100755 ollama/app/lifecycle/server_unix.go delete mode 100755 ollama/app/lifecycle/server_windows.go delete mode 100755 ollama/app/lifecycle/updater.go delete mode 100755 ollama/app/lifecycle/updater_nonwindows.go delete mode 100755 ollama/app/lifecycle/updater_windows.go delete mode 100755 ollama/app/main.go delete mode 100755 ollama/app/ollama.iss delete mode 100755 ollama/app/ollama.rc delete mode 100755 ollama/app/ollama_welcome.ps1 delete mode 100755 ollama/app/store/store.go delete mode 100755 ollama/app/store/store_darwin.go delete mode 100755 ollama/app/store/store_linux.go delete mode 100755 ollama/app/store/store_windows.go delete mode 100755 ollama/app/tray/commontray/types.go delete mode 100755 ollama/app/tray/tray.go delete mode 100755 ollama/app/tray/tray_nonwindows.go delete mode 100755 ollama/app/tray/tray_windows.go delete mode 100755 ollama/app/tray/wintray/eventloop.go delete mode 100755 ollama/app/tray/wintray/menus.go delete mode 100755 ollama/app/tray/wintray/messages.go delete mode 100755 ollama/app/tray/wintray/notifyicon.go delete mode 100755 ollama/app/tray/wintray/tray.go delete mode 100755 ollama/app/tray/wintray/w32api.go delete mode 100755 ollama/app/tray/wintray/winclass.go delete mode 100755 ollama/auth/auth.go delete mode 100755 ollama/cmd/cmd.go delete mode 100755 ollama/cmd/interactive.go delete mode 100755 ollama/cmd/interactive_test.go delete mode 100755 ollama/cmd/start.go delete mode 100755 ollama/cmd/start_darwin.go delete mode 100755 ollama/cmd/start_default.go delete mode 100755 ollama/cmd/start_windows.go delete mode 100755 ollama/convert/convert.go delete mode 100755 ollama/convert/convert_gemma.go delete mode 100755 ollama/convert/convert_llama.go delete mode 100755 ollama/convert/convert_mixtral.go delete mode 100755 ollama/convert/convert_test.go delete mode 100755 ollama/convert/fs.go delete mode 100755 ollama/convert/reader.go delete mode 100755 ollama/convert/reader_safetensors.go delete mode 100755 ollama/convert/reader_torch.go delete mode 100755 ollama/convert/sentencepiece/sentencepiece_model.pb.go delete mode 100755 ollama/convert/sentencepiece_model.proto delete mode 100755 ollama/convert/testdata/Meta-Llama-3-8B-Instruct.json delete mode 100755 ollama/convert/testdata/Mistral-7B-Instruct-v0.2.json delete mode 100755 ollama/convert/testdata/Mixtral-8x7B-Instruct-v0.1.json delete mode 100755 ollama/convert/testdata/gemma-2b-it.json delete mode 100755 ollama/convert/tokenizer.go delete mode 100755 ollama/convert/tokenizer_spm.go delete mode 100755 ollama/docs/README.md delete mode 100755 ollama/docs/api.md delete mode 100755 ollama/docs/development.md delete mode 100755 ollama/docs/docker.md delete mode 100755 ollama/docs/faq.md delete mode 100755 ollama/docs/gpu.md delete mode 100755 ollama/docs/import.md delete mode 100755 ollama/docs/linux.md delete mode 100755 ollama/docs/modelfile.md delete mode 100755 ollama/docs/openai.md delete mode 100755 ollama/docs/template.md delete mode 100755 ollama/docs/troubleshooting.md delete mode 100755 ollama/docs/tutorials.md delete mode 100755 ollama/docs/tutorials/fly-gpu.md delete mode 100755 ollama/docs/tutorials/langchainjs.md delete mode 100755 ollama/docs/tutorials/langchainpy.md delete mode 100755 ollama/docs/tutorials/nvidia-jetson.md delete mode 100755 ollama/docs/windows.md delete mode 100755 ollama/envconfig/config.go delete mode 100755 ollama/envconfig/config_test.go delete mode 100755 ollama/examples/.gitignore delete mode 100755 ollama/examples/README.md delete mode 100755 ollama/examples/flyio/.gitignore delete mode 100755 ollama/examples/flyio/README.md delete mode 100755 ollama/examples/go-chat/main.go delete mode 100755 ollama/examples/go-generate-streaming/main.go delete mode 100755 ollama/examples/go-generate/main.go delete mode 100755 ollama/examples/go-http-generate/main.go delete mode 100755 ollama/examples/go-multimodal/main.go delete mode 100755 ollama/examples/go-pull-progress/main.go delete mode 100755 ollama/examples/jupyter-notebook/README.md delete mode 100755 ollama/examples/jupyter-notebook/ollama.ipynb delete mode 100755 ollama/examples/kubernetes/README.md delete mode 100755 ollama/examples/kubernetes/cpu.yaml delete mode 100755 ollama/examples/kubernetes/gpu.yaml delete mode 100755 ollama/examples/langchain-python-rag-document/README.md delete mode 100755 ollama/examples/langchain-python-rag-document/main.py delete mode 100755 ollama/examples/langchain-python-rag-document/requirements.txt delete mode 100755 ollama/examples/langchain-python-rag-privategpt/.gitignore delete mode 100755 ollama/examples/langchain-python-rag-privategpt/LICENSE delete mode 100755 ollama/examples/langchain-python-rag-privategpt/README.md delete mode 100755 ollama/examples/langchain-python-rag-privategpt/constants.py delete mode 100755 ollama/examples/langchain-python-rag-privategpt/ingest.py delete mode 100755 ollama/examples/langchain-python-rag-privategpt/poetry.lock delete mode 100755 ollama/examples/langchain-python-rag-privategpt/privateGPT.py delete mode 100755 ollama/examples/langchain-python-rag-privategpt/pyproject.toml delete mode 100755 ollama/examples/langchain-python-rag-privategpt/requirements.txt delete mode 100755 ollama/examples/langchain-python-rag-websummary/README.md delete mode 100755 ollama/examples/langchain-python-rag-websummary/main.py delete mode 100755 ollama/examples/langchain-python-rag-websummary/requirements.txt delete mode 100755 ollama/examples/langchain-python-simple/README.md delete mode 100755 ollama/examples/langchain-python-simple/main.py delete mode 100755 ollama/examples/langchain-python-simple/requirements.txt delete mode 100755 ollama/examples/langchain-typescript-simple/README.md delete mode 100755 ollama/examples/langchain-typescript-simple/main.ts delete mode 100755 ollama/examples/langchain-typescript-simple/package-lock.json delete mode 100755 ollama/examples/langchain-typescript-simple/package.json delete mode 100755 ollama/examples/modelfile-mario/Modelfile delete mode 100755 ollama/examples/modelfile-mario/logo.png delete mode 100755 ollama/examples/modelfile-mario/readme.md delete mode 100755 ollama/examples/python-dockerit/Modelfile delete mode 100755 ollama/examples/python-dockerit/README.md delete mode 100755 ollama/examples/python-dockerit/dockerit.py delete mode 100755 ollama/examples/python-dockerit/requirements.txt delete mode 100755 ollama/examples/python-json-datagenerator/predefinedschema.py delete mode 100755 ollama/examples/python-json-datagenerator/randomaddresses.py delete mode 100755 ollama/examples/python-json-datagenerator/readme.md delete mode 100755 ollama/examples/python-json-datagenerator/requirements.txt delete mode 100755 ollama/examples/python-loganalysis/Modelfile delete mode 100755 ollama/examples/python-loganalysis/loganalysis.py delete mode 100755 ollama/examples/python-loganalysis/logtest.logfile delete mode 100755 ollama/examples/python-loganalysis/readme.md delete mode 100755 ollama/examples/python-loganalysis/requirements.txt delete mode 100755 ollama/examples/python-rag-newssummary/README.md delete mode 100755 ollama/examples/python-rag-newssummary/requirements.txt delete mode 100755 ollama/examples/python-rag-newssummary/summ.py delete mode 100755 ollama/examples/python-rag-newssummary/utils.py delete mode 100755 ollama/examples/python-simplechat/client.py delete mode 100755 ollama/examples/python-simplechat/readme.md delete mode 100755 ollama/examples/python-simplechat/requirements.txt delete mode 100755 ollama/examples/python-simplegenerate/README.md delete mode 100755 ollama/examples/python-simplegenerate/client.py delete mode 100755 ollama/examples/python-simplegenerate/requirements.txt delete mode 100755 ollama/examples/typescript-functioncalling/extractemail.ts delete mode 100755 ollama/examples/typescript-functioncalling/extractwp.ts delete mode 100755 ollama/examples/typescript-functioncalling/info.txt delete mode 100755 ollama/examples/typescript-functioncalling/package-lock.json delete mode 100755 ollama/examples/typescript-functioncalling/package.json delete mode 100755 ollama/examples/typescript-functioncalling/readme.md delete mode 100755 ollama/examples/typescript-functioncalling/wp.txt delete mode 100755 ollama/examples/typescript-mentors/.gitignore delete mode 100755 ollama/examples/typescript-mentors/README.md delete mode 100755 ollama/examples/typescript-mentors/character-generator.ts delete mode 100755 ollama/examples/typescript-mentors/mentors.ts delete mode 100755 ollama/examples/typescript-mentors/package.json delete mode 100755 ollama/examples/typescript-simplechat/client.ts delete mode 100755 ollama/examples/typescript-simplechat/package.json delete mode 100755 ollama/examples/typescript-simplechat/readme.md delete mode 100755 ollama/format/bytes.go delete mode 100755 ollama/format/format.go delete mode 100755 ollama/format/format_test.go delete mode 100755 ollama/format/time.go delete mode 100755 ollama/format/time_test.go delete mode 100755 ollama/go.mod delete mode 100755 ollama/go.sum delete mode 100755 ollama/gpu/amd_common.go delete mode 100755 ollama/gpu/amd_hip_windows.go delete mode 100755 ollama/gpu/amd_linux.go delete mode 100755 ollama/gpu/amd_windows.go delete mode 100755 ollama/gpu/assets.go delete mode 100755 ollama/gpu/cpu_common.go delete mode 100755 ollama/gpu/cuda_common.go delete mode 100755 ollama/gpu/gpu.go delete mode 100755 ollama/gpu/gpu_darwin.go delete mode 100755 ollama/gpu/gpu_info.h delete mode 100755 ollama/gpu/gpu_info_cudart.c delete mode 100755 ollama/gpu/gpu_info_cudart.h delete mode 100755 ollama/gpu/gpu_info_darwin.h delete mode 100755 ollama/gpu/gpu_info_darwin.m delete mode 100755 ollama/gpu/gpu_info_nvcuda.c delete mode 100755 ollama/gpu/gpu_info_nvcuda.h delete mode 100755 ollama/gpu/gpu_info_nvml.c delete mode 100755 ollama/gpu/gpu_info_nvml.h delete mode 100755 ollama/gpu/gpu_info_oneapi.c delete mode 100755 ollama/gpu/gpu_info_oneapi.h delete mode 100755 ollama/gpu/gpu_linux.go delete mode 100755 ollama/gpu/gpu_oneapi.go delete mode 100755 ollama/gpu/gpu_test.go delete mode 100755 ollama/gpu/gpu_windows.go delete mode 100755 ollama/gpu/types.go delete mode 100755 ollama/integration/README.md delete mode 100755 ollama/integration/basic_test.go delete mode 100755 ollama/integration/concurrency_test.go delete mode 100755 ollama/integration/context_test.go delete mode 100755 ollama/integration/embed_test.go delete mode 100755 ollama/integration/llm_image_test.go delete mode 100755 ollama/integration/llm_test.go delete mode 100755 ollama/integration/max_queue_test.go delete mode 100755 ollama/integration/utils_test.go delete mode 100755 ollama/llm/ext_server/CMakeLists.txt delete mode 100755 ollama/llm/ext_server/httplib.h delete mode 100755 ollama/llm/ext_server/json.hpp delete mode 100755 ollama/llm/ext_server/server.cpp delete mode 100755 ollama/llm/ext_server/utils.hpp delete mode 100755 ollama/llm/filetype.go delete mode 100755 ollama/llm/generate/gen_common.sh delete mode 100755 ollama/llm/generate/gen_darwin.sh delete mode 100755 ollama/llm/generate/gen_linux.sh delete mode 100755 ollama/llm/generate/gen_windows.ps1 delete mode 100755 ollama/llm/generate/generate_darwin.go delete mode 100755 ollama/llm/generate/generate_linux.go delete mode 100755 ollama/llm/generate/generate_windows.go delete mode 100755 ollama/llm/ggla.go delete mode 100755 ollama/llm/ggml.go delete mode 100755 ollama/llm/ggml_test.go delete mode 100755 ollama/llm/gguf.go delete mode 100755 ollama/llm/llama.cpp/.clang-tidy delete mode 100755 ollama/llm/llama.cpp/.devops/cloud-v-pipeline delete mode 100755 ollama/llm/llama.cpp/.devops/full-cuda.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/full-rocm.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/full.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cli-cuda.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cli-intel.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cli-rocm.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cli-vulkan.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cli.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cpp-cuda.srpm.spec delete mode 100755 ollama/llm/llama.cpp/.devops/llama-cpp.srpm.spec delete mode 100755 ollama/llm/llama.cpp/.devops/llama-server-cuda.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-server-intel.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-server-rocm.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-server-vulkan.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/llama-server.Dockerfile delete mode 100755 ollama/llm/llama.cpp/.devops/nix/apps.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/devshells.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/docker.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/jetson-support.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/nixpkgs-instances.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/package.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/scope.nix delete mode 100755 ollama/llm/llama.cpp/.devops/nix/sif.nix delete mode 100755 ollama/llm/llama.cpp/.devops/tools.sh delete mode 100755 ollama/llm/llama.cpp/.dockerignore delete mode 100755 ollama/llm/llama.cpp/.ecrc delete mode 100755 ollama/llm/llama.cpp/.editorconfig delete mode 100755 ollama/llm/llama.cpp/.flake8 delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/01-bug-low.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/02-bug-medium.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/03-bug-high.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/04-bug-critical.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/05-enhancement.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/06-research.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/07-refactor.yml delete mode 100755 ollama/llm/llama.cpp/.github/ISSUE_TEMPLATE/config.yml delete mode 100755 ollama/llm/llama.cpp/.github/labeler.yml delete mode 100755 ollama/llm/llama.cpp/.github/pull_request_template.md delete mode 100755 ollama/llm/llama.cpp/.github/workflows/bench.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/build.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/close-issue.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/docker.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/editorconfig.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/gguf-publish.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/labeler.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/nix-ci-aarch64.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/nix-ci.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/nix-flake-update.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/nix-publish-flake.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/python-check-requirements.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/python-lint.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/python-type-check.yml delete mode 100755 ollama/llm/llama.cpp/.github/workflows/server.yml delete mode 100755 ollama/llm/llama.cpp/.gitignore delete mode 100755 ollama/llm/llama.cpp/.gitmodules delete mode 100755 ollama/llm/llama.cpp/.pre-commit-config.yaml delete mode 100755 ollama/llm/llama.cpp/AUTHORS delete mode 100755 ollama/llm/llama.cpp/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/CMakePresets.json delete mode 100755 ollama/llm/llama.cpp/CONTRIBUTING.md delete mode 100755 ollama/llm/llama.cpp/LICENSE delete mode 100755 ollama/llm/llama.cpp/Makefile delete mode 100755 ollama/llm/llama.cpp/Package.swift delete mode 100755 ollama/llm/llama.cpp/README.md delete mode 100755 ollama/llm/llama.cpp/SECURITY.md delete mode 100755 ollama/llm/llama.cpp/ci/README.md delete mode 100755 ollama/llm/llama.cpp/ci/run.sh delete mode 100755 ollama/llm/llama.cpp/cmake/arm64-windows-llvm.cmake delete mode 100755 ollama/llm/llama.cpp/cmake/arm64-windows-msvc.cmake delete mode 100755 ollama/llm/llama.cpp/cmake/build-info.cmake delete mode 100755 ollama/llm/llama.cpp/cmake/git-vars.cmake delete mode 100755 ollama/llm/llama.cpp/cmake/llama-config.cmake.in delete mode 100755 ollama/llm/llama.cpp/cmake/llama.pc.in delete mode 100755 ollama/llm/llama.cpp/common/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/common/base64.hpp delete mode 100755 ollama/llm/llama.cpp/common/build-info.cpp.in delete mode 100755 ollama/llm/llama.cpp/common/common.cpp delete mode 100755 ollama/llm/llama.cpp/common/common.h delete mode 100755 ollama/llm/llama.cpp/common/console.cpp delete mode 100755 ollama/llm/llama.cpp/common/console.h delete mode 100755 ollama/llm/llama.cpp/common/grammar-parser.cpp delete mode 100755 ollama/llm/llama.cpp/common/grammar-parser.h delete mode 100755 ollama/llm/llama.cpp/common/json-schema-to-grammar.cpp delete mode 100755 ollama/llm/llama.cpp/common/json-schema-to-grammar.h delete mode 100755 ollama/llm/llama.cpp/common/json.hpp delete mode 100755 ollama/llm/llama.cpp/common/log.h delete mode 100755 ollama/llm/llama.cpp/common/ngram-cache.cpp delete mode 100755 ollama/llm/llama.cpp/common/ngram-cache.h delete mode 100755 ollama/llm/llama.cpp/common/sampling.cpp delete mode 100755 ollama/llm/llama.cpp/common/sampling.h delete mode 100755 ollama/llm/llama.cpp/common/stb_image.h delete mode 100755 ollama/llm/llama.cpp/common/train.cpp delete mode 100755 ollama/llm/llama.cpp/common/train.h delete mode 100755 ollama/llm/llama.cpp/convert_hf_to_gguf.py delete mode 100755 ollama/llm/llama.cpp/convert_hf_to_gguf_update.py delete mode 100755 ollama/llm/llama.cpp/convert_llama_ggml_to_gguf.py delete mode 100755 ollama/llm/llama.cpp/convert_lora_to_gguf.py delete mode 100755 ollama/llm/llama.cpp/docs/android.md delete mode 100755 ollama/llm/llama.cpp/docs/backend/BLIS.md delete mode 100755 ollama/llm/llama.cpp/docs/backend/SYCL.md delete mode 100755 ollama/llm/llama.cpp/docs/build.md delete mode 100755 ollama/llm/llama.cpp/docs/development/HOWTO-add-model.md delete mode 100755 ollama/llm/llama.cpp/docs/development/debugging-tests.md delete mode 100755 ollama/llm/llama.cpp/docs/development/llama-star/idea-arch.key delete mode 100755 ollama/llm/llama.cpp/docs/development/llama-star/idea-arch.pdf delete mode 100755 ollama/llm/llama.cpp/docs/development/token_generation_performance_tips.md delete mode 100755 ollama/llm/llama.cpp/docs/docker.md delete mode 100755 ollama/llm/llama.cpp/docs/install.md delete mode 100755 ollama/llm/llama.cpp/examples/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/Miku.sh delete mode 100755 ollama/llm/llama.cpp/examples/baby-llama/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/baby-llama/baby-llama.cpp delete mode 100755 ollama/llm/llama.cpp/examples/base-translate.sh delete mode 100755 ollama/llm/llama.cpp/examples/batched-bench/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/batched-bench/README.md delete mode 100755 ollama/llm/llama.cpp/examples/batched-bench/batched-bench.cpp delete mode 100755 ollama/llm/llama.cpp/examples/batched.swift/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/batched.swift/Makefile delete mode 100755 ollama/llm/llama.cpp/examples/batched.swift/Package.swift delete mode 100755 ollama/llm/llama.cpp/examples/batched.swift/README.md delete mode 100755 ollama/llm/llama.cpp/examples/batched.swift/Sources/main.swift delete mode 100755 ollama/llm/llama.cpp/examples/batched/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/batched/README.md delete mode 100755 ollama/llm/llama.cpp/examples/batched/batched.cpp delete mode 100755 ollama/llm/llama.cpp/examples/benchmark/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/benchmark/benchmark-matmult.cpp delete mode 100755 ollama/llm/llama.cpp/examples/chat-13B.bat delete mode 100755 ollama/llm/llama.cpp/examples/chat-13B.sh delete mode 100755 ollama/llm/llama.cpp/examples/chat-persistent.sh delete mode 100755 ollama/llm/llama.cpp/examples/chat-vicuna.sh delete mode 100755 ollama/llm/llama.cpp/examples/chat.sh delete mode 100755 ollama/llm/llama.cpp/examples/convert-llama2c-to-ggml/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/convert-llama2c-to-ggml/README.md delete mode 100755 ollama/llm/llama.cpp/examples/convert-llama2c-to-ggml/convert-llama2c-to-ggml.cpp delete mode 100755 ollama/llm/llama.cpp/examples/convert_legacy_llama.py delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/README.md delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/completions.txt delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/cvector-generator.cpp delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/mean.hpp delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/negative.txt delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/pca.hpp delete mode 100755 ollama/llm/llama.cpp/examples/cvector-generator/positive.txt delete mode 100755 ollama/llm/llama.cpp/examples/deprecation-warning/README.md delete mode 100755 ollama/llm/llama.cpp/examples/deprecation-warning/deprecation-warning.cpp delete mode 100755 ollama/llm/llama.cpp/examples/embedding/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/embedding/README.md delete mode 100755 ollama/llm/llama.cpp/examples/embedding/embedding.cpp delete mode 100755 ollama/llm/llama.cpp/examples/eval-callback/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/eval-callback/README.md delete mode 100755 ollama/llm/llama.cpp/examples/eval-callback/eval-callback.cpp delete mode 100755 ollama/llm/llama.cpp/examples/export-lora/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/export-lora/README.md delete mode 100755 ollama/llm/llama.cpp/examples/export-lora/export-lora.cpp delete mode 100755 ollama/llm/llama.cpp/examples/gbnf-validator/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/gbnf-validator/gbnf-validator.cpp delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/README.md delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/rotate-bits/package.json delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/rotate-bits/rotate-bits.h delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha1/package.json delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha1/sha1.c delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha1/sha1.h delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha256/package.json delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha256/sha256.c delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/sha256/sha256.h delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/xxhash/clib.json delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/xxhash/xxhash.c delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/deps/xxhash/xxhash.h delete mode 100755 ollama/llm/llama.cpp/examples/gguf-hash/gguf-hash.cpp delete mode 100755 ollama/llm/llama.cpp/examples/gguf-split/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/gguf-split/README.md delete mode 100755 ollama/llm/llama.cpp/examples/gguf-split/gguf-split.cpp delete mode 100755 ollama/llm/llama.cpp/examples/gguf-split/tests.sh delete mode 100755 ollama/llm/llama.cpp/examples/gguf/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/gguf/gguf.cpp delete mode 100755 ollama/llm/llama.cpp/examples/gritlm/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/gritlm/README.md delete mode 100755 ollama/llm/llama.cpp/examples/gritlm/gritlm.cpp delete mode 100755 ollama/llm/llama.cpp/examples/imatrix/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/imatrix/README.md delete mode 100755 ollama/llm/llama.cpp/examples/imatrix/imatrix.cpp delete mode 100755 ollama/llm/llama.cpp/examples/infill/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/infill/README.md delete mode 100755 ollama/llm/llama.cpp/examples/infill/infill.cpp delete mode 100755 ollama/llm/llama.cpp/examples/jeopardy/README.md delete mode 100755 ollama/llm/llama.cpp/examples/jeopardy/graph.py delete mode 100755 ollama/llm/llama.cpp/examples/jeopardy/jeopardy.sh delete mode 100755 ollama/llm/llama.cpp/examples/jeopardy/qasheet.csv delete mode 100755 ollama/llm/llama.cpp/examples/jeopardy/questions.txt delete mode 100755 ollama/llm/llama.cpp/examples/json_schema_pydantic_example.py delete mode 100755 ollama/llm/llama.cpp/examples/json_schema_to_grammar.py delete mode 100755 ollama/llm/llama.cpp/examples/llama-bench/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/llama-bench/README.md delete mode 100755 ollama/llm/llama.cpp/examples/llama-bench/llama-bench.cpp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/README.md delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/build.gradle.kts delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/proguard-rules.pro delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/AndroidManifest.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/Downloadable.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MainViewModel.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Color.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Theme.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Type.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/values/colors.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/values/strings.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/values/themes.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/xml/backup_rules.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/app/src/main/res/xml/data_extraction_rules.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/build.gradle.kts delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/gradle.properties delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/gradle/wrapper/gradle-wrapper.jar delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/gradlew delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/build.gradle.kts delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/consumer-rules.pro delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/proguard-rules.pro delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/androidTest/java/android/llama/cpp/ExampleInstrumentedTest.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/main/AndroidManifest.xml delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/main/cpp/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/main/cpp/llama-android.cpp delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/main/java/android/llama/cpp/LLamaAndroid.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/llama/src/test/java/android/llama/cpp/ExampleUnitTest.kt delete mode 100755 ollama/llm/llama.cpp/examples/llama.android/settings.gradle.kts delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/README.md delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/Assets.xcassets/Contents.json delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/Resources/models/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/UI/DownloadButton.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/UI/InputButton.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/UI/LoadCustomButton.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.swiftui/llama.swiftui/llama_swiftuiApp.swift delete mode 100755 ollama/llm/llama.cpp/examples/llama.vim delete mode 100755 ollama/llm/llama.cpp/examples/llava/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/llava/MobileVLM-README.md delete mode 100755 ollama/llm/llama.cpp/examples/llava/README.md delete mode 100755 ollama/llm/llama.cpp/examples/llava/android/adb_run.sh delete mode 100755 ollama/llm/llama.cpp/examples/llava/android/build_64.sh delete mode 100755 ollama/llm/llama.cpp/examples/llava/clip.cpp delete mode 100755 ollama/llm/llama.cpp/examples/llava/clip.h delete mode 100755 ollama/llm/llama.cpp/examples/llava/convert_image_encoder_to_gguf.py delete mode 100755 ollama/llm/llama.cpp/examples/llava/llava-cli.cpp delete mode 100755 ollama/llm/llama.cpp/examples/llava/llava.cpp delete mode 100755 ollama/llm/llama.cpp/examples/llava/llava.h delete mode 100755 ollama/llm/llama.cpp/examples/llava/llava_surgery.py delete mode 100755 ollama/llm/llama.cpp/examples/llava/llava_surgery_v2.py delete mode 100755 ollama/llm/llama.cpp/examples/llava/requirements.txt delete mode 100755 ollama/llm/llama.cpp/examples/llm.vim delete mode 100755 ollama/llm/llama.cpp/examples/lookahead/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/lookahead/README.md delete mode 100755 ollama/llm/llama.cpp/examples/lookahead/lookahead.cpp delete mode 100755 ollama/llm/llama.cpp/examples/lookup/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/lookup/README.md delete mode 100755 ollama/llm/llama.cpp/examples/lookup/lookup-create.cpp delete mode 100755 ollama/llm/llama.cpp/examples/lookup/lookup-merge.cpp delete mode 100755 ollama/llm/llama.cpp/examples/lookup/lookup-stats.cpp delete mode 100755 ollama/llm/llama.cpp/examples/lookup/lookup.cpp delete mode 100755 ollama/llm/llama.cpp/examples/main-cmake-pkg/.gitignore delete mode 100755 ollama/llm/llama.cpp/examples/main-cmake-pkg/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/main-cmake-pkg/README.md delete mode 100755 ollama/llm/llama.cpp/examples/main/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/main/README.md delete mode 100755 ollama/llm/llama.cpp/examples/main/main.cpp delete mode 100755 ollama/llm/llama.cpp/examples/parallel/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/parallel/README.md delete mode 100755 ollama/llm/llama.cpp/examples/parallel/parallel.cpp delete mode 100755 ollama/llm/llama.cpp/examples/passkey/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/passkey/README.md delete mode 100755 ollama/llm/llama.cpp/examples/passkey/passkey.cpp delete mode 100755 ollama/llm/llama.cpp/examples/perplexity/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/perplexity/README.md delete mode 100755 ollama/llm/llama.cpp/examples/perplexity/perplexity.cpp delete mode 100755 ollama/llm/llama.cpp/examples/pydantic_models_to_grammar.py delete mode 100755 ollama/llm/llama.cpp/examples/pydantic_models_to_grammar_examples.py delete mode 100755 ollama/llm/llama.cpp/examples/quantize-stats/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/quantize-stats/quantize-stats.cpp delete mode 100755 ollama/llm/llama.cpp/examples/quantize/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/quantize/README.md delete mode 100755 ollama/llm/llama.cpp/examples/quantize/quantize.cpp delete mode 100755 ollama/llm/llama.cpp/examples/quantize/tests.sh delete mode 100755 ollama/llm/llama.cpp/examples/reason-act.sh delete mode 100755 ollama/llm/llama.cpp/examples/regex_to_grammar.py delete mode 100755 ollama/llm/llama.cpp/examples/retrieval/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/retrieval/README.md delete mode 100755 ollama/llm/llama.cpp/examples/retrieval/retrieval.cpp delete mode 100755 ollama/llm/llama.cpp/examples/rpc/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/rpc/README.md delete mode 100755 ollama/llm/llama.cpp/examples/rpc/rpc-server.cpp delete mode 100755 ollama/llm/llama.cpp/examples/save-load-state/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/save-load-state/save-load-state.cpp delete mode 100755 ollama/llm/llama.cpp/examples/server-llama2-13B.sh delete mode 100755 ollama/llm/llama.cpp/examples/server/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/server/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/bench/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/bench/bench.py delete mode 100755 ollama/llm/llama.cpp/examples/server/bench/prometheus.yml delete mode 100755 ollama/llm/llama.cpp/examples/server/bench/requirements.txt delete mode 100755 ollama/llm/llama.cpp/examples/server/bench/script.js delete mode 100755 ollama/llm/llama.cpp/examples/server/chat-llama2.sh delete mode 100755 ollama/llm/llama.cpp/examples/server/chat.mjs delete mode 100755 ollama/llm/llama.cpp/examples/server/chat.sh delete mode 100755 ollama/llm/llama.cpp/examples/server/deps.sh delete mode 100755 ollama/llm/llama.cpp/examples/server/httplib.h delete mode 100755 ollama/llm/llama.cpp/examples/server/public/colorthemes.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/completion.js delete mode 100755 ollama/llm/llama.cpp/examples/server/public/favicon.ico delete mode 100755 ollama/llm/llama.cpp/examples/server/public/index-new.html delete mode 100755 ollama/llm/llama.cpp/examples/server/public/index.html delete mode 100755 ollama/llm/llama.cpp/examples/server/public/index.js delete mode 100755 ollama/llm/llama.cpp/examples/server/public/json-schema-to-grammar.mjs delete mode 100755 ollama/llm/llama.cpp/examples/server/public/prompt-formats.js delete mode 100755 ollama/llm/llama.cpp/examples/server/public/style.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/system-prompts.js delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-beeninorder.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-ketivah.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-mangotango.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-playground.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-polarnight.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public/theme-snowstorm.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/datautils.mjs delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/index.html delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/readme.md delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/simplechat.css delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/simplechat.js delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/simplechat_screens.webp delete mode 100755 ollama/llm/llama.cpp/examples/server/public_simplechat/ui.mjs delete mode 100755 ollama/llm/llama.cpp/examples/server/server.cpp delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/embeddings.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/environment.py delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/issues.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/lora.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/parallel.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/passkey.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/results.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/security.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/server.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/slotsave.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/steps/steps.py delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/features/wrong_usages.feature delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/requirements.txt delete mode 100755 ollama/llm/llama.cpp/examples/server/tests/tests.sh delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/buttons-top/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/buttons-top/buttons_top.png delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/buttons-top/favicon.ico delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/buttons-top/index.html delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/README.md delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/favicon.ico delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/index.html delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/llama_cpp.png delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/llamapattern.png delete mode 100755 ollama/llm/llama.cpp/examples/server/themes/wild/wild.png delete mode 100755 ollama/llm/llama.cpp/examples/server/utils.hpp delete mode 100755 ollama/llm/llama.cpp/examples/server_embd.py delete mode 100755 ollama/llm/llama.cpp/examples/simple/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/simple/README.md delete mode 100755 ollama/llm/llama.cpp/examples/simple/simple.cpp delete mode 100755 ollama/llm/llama.cpp/examples/speculative/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/speculative/README.md delete mode 100755 ollama/llm/llama.cpp/examples/speculative/speculative.cpp delete mode 100755 ollama/llm/llama.cpp/examples/sycl/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/sycl/README.md delete mode 100755 ollama/llm/llama.cpp/examples/sycl/build.sh delete mode 100755 ollama/llm/llama.cpp/examples/sycl/ls-sycl-device.cpp delete mode 100755 ollama/llm/llama.cpp/examples/sycl/run-llama2.sh delete mode 100755 ollama/llm/llama.cpp/examples/sycl/win-build-sycl.bat delete mode 100755 ollama/llm/llama.cpp/examples/sycl/win-run-llama2.bat delete mode 100755 ollama/llm/llama.cpp/examples/tokenize/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/examples/tokenize/tokenize.cpp delete mode 100755 ollama/llm/llama.cpp/examples/ts-type-to-grammar.sh delete mode 100755 ollama/llm/llama.cpp/flake.lock delete mode 100755 ollama/llm/llama.cpp/flake.nix delete mode 100755 ollama/llm/llama.cpp/ggml/.gitignore delete mode 100755 ollama/llm/llama.cpp/ggml/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/ggml/cmake/FindSIMD.cmake delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-alloc.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-backend.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-blas.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-cann.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-cuda.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-kompute.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-metal.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-rpc.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-sycl.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml-vulkan.h delete mode 100755 ollama/llm/llama.cpp/ggml/include/ggml.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-aarch64.c delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-aarch64.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-alloc.c delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-backend-impl.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-backend.c delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-blas.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/.clang-format delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/Doxyfile delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/acl_tensor.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/acl_tensor.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/aclnn_ops.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/aclnn_ops.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/common.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/ascendc_kernels.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/dup.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/get_row_f16.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/get_row_f32.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/get_row_q4_0.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/get_row_q8_0.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/quantize_f16_q8_0.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/quantize_f32_q8_0.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cann/kernels/quantize_float_to_q4_0.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-common.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/acc.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/acc.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/arange.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/arange.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/argsort.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/argsort.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/binbcast.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/binbcast.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/clamp.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/clamp.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/common.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/concat.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/concat.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/conv-transpose-1d.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/conv-transpose-1d.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/convert.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/convert.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/cpy.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/cpy.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/dequantize.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/diagmask.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/diagmask.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/dmmv.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/dmmv.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-common.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-tile-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-tile-f16.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-tile-f32.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-tile-f32.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-vec-f16.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-vec-f32.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn-wmma-f16.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/fattn.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/getrows.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/getrows.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/im2col.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/im2col.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/mma.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/mmq.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/mmq.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/mmvq.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/mmvq.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/norm.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/norm.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/pad.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/pad.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/pool2d.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/pool2d.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/quantize.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/quantize.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/rope.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/rope.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/scale.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/scale.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/softmax.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/softmax.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/sumrows.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/sumrows.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-f16-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q4_1-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q5_1-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs128-q8_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs256-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f16-instance-hs64-f16-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-f16-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q4_1-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q5_1-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs128-q8_0-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs256-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-f16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-vec-f32-instance-hs64-f16-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-wmma-f16-instance-kqfloat-cpb16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-wmma-f16-instance-kqfloat-cpb32.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-wmma-f16-instance-kqhalf-cpb16.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-wmma-f16-instance-kqhalf-cpb32.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/fattn-wmma-f16-instance-kqhalf-cpb8.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/generate_cu_files.py delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_s.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_s.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xs.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xxs.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_s.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_xxs.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_nl.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_xs.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q2_k.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q3_k.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_k.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_1.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_k.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q6_k.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/template-instances/mmq-instance-q8_0.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/tsembd.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/tsembd.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/unary.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/unary.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/upscale.cu delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/upscale.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/vecdotq.cuh delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/vendors/cuda.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/vendors/hip.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-cuda/vendors/musa.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-impl.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-kompute.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-metal.m delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-quants.c delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-quants.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-rpc.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/backend.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/common.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/common.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/concat.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/concat.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/conv.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/conv.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/convert.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/convert.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/dequantize.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/dmmv.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/dmmv.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/dpct/helper.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/mmq.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/mmq.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/mmvq.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/mmvq.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/norm.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/norm.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/presets.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/rope.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/rope.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/softmax.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/softmax.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/tsembd.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/tsembd.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-sycl/vecdotq.hpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml-vulkan.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/ggml.c delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/common.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_add.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_addrow.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_cpy_f16_f16.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_cpy_f16_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_cpy_f32_f16.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_cpy_f32_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_diagmask.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_gelu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows_f16.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows_q4_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows_q4_1.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_getrows_q6_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_f16.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_mat_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_q4_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_q4_1.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_q6_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mat_q8_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mv_q_n.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_mul_mv_q_n_pre.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_norm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_relu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_rmsnorm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_rope_f16.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_rope_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_scale.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_scale_8.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_silu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/op_softmax.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/kompute-shaders/rope_common.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/llamafile/sgemm.cpp delete mode 100755 ollama/llm/llama.cpp/ggml/src/llamafile/sgemm.h delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/add.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/argsort.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/clamp.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/concat.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/copy.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_f32.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_funcs.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_head.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_iq4_nl.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q2_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q3_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q4_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q4_1.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q4_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q5_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q5_1.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q5_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q6_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/dequant_q8_0.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/diag_mask_inf.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/div.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/gelu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/gelu_quick.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/generic_binary_head.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/generic_head.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/generic_unary_head.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/get_rows.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/get_rows_quant.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/group_norm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/im2col.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/leaky_relu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_split_k_reduce.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_base.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_nc.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_p021.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/mul_mm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/norm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/pad.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/relu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/rms_norm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/rope_head.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/rope_neox.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/rope_norm.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/scale.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/silu.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/soft_max.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/square.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/sum_rows.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/tanh.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/timestep_embedding.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/types.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/upscale.comp delete mode 100755 ollama/llm/llama.cpp/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp delete mode 100755 ollama/llm/llama.cpp/gguf-py/LICENSE delete mode 100755 ollama/llm/llama.cpp/gguf-py/README.md delete mode 100755 ollama/llm/llama.cpp/gguf-py/examples/reader.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/examples/writer.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/__init__.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/constants.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/gguf.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/gguf_reader.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/gguf_writer.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/lazy.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/metadata.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/py.typed delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/quants.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/tensor_mapping.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/utility.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/gguf/vocab.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/pyproject.toml delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/__init__.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/gguf_convert_endian.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/gguf_dump.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/gguf_hash.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/gguf_new_metadata.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/scripts/gguf_set_metadata.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/tests/__init__.py delete mode 100755 ollama/llm/llama.cpp/gguf-py/tests/test_metadata.py delete mode 100755 ollama/llm/llama.cpp/grammars/README.md delete mode 100755 ollama/llm/llama.cpp/grammars/arithmetic.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/c.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/chess.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/japanese.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/json.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/json_arr.gbnf delete mode 100755 ollama/llm/llama.cpp/grammars/list.gbnf delete mode 100755 ollama/llm/llama.cpp/include/llama.h delete mode 100755 ollama/llm/llama.cpp/media/llama-leader.jpeg delete mode 100755 ollama/llm/llama.cpp/media/llama0-banner.png delete mode 100755 ollama/llm/llama.cpp/media/llama0-logo.png delete mode 100755 ollama/llm/llama.cpp/media/llama1-banner.png delete mode 100755 ollama/llm/llama.cpp/media/llama1-logo.png delete mode 100755 ollama/llm/llama.cpp/media/matmul.png delete mode 100755 ollama/llm/llama.cpp/media/matmul.svg delete mode 100755 ollama/llm/llama.cpp/models/.editorconfig delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-aquila.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-baichuan.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-bert-bge.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-bert-bge.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-bert-bge.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-command-r.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-command-r.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-command-r.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-coder.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-coder.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-coder.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-llm.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-llm.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-deepseek-llm.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-falcon.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-falcon.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-falcon.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-gpt-2.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-gpt-2.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-gpt-2.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-gpt-neox.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-bpe.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-bpe.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-bpe.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-spm.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-spm.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-llama-spm.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-mpt.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-mpt.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-mpt.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-phi-3.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-phi-3.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-phi-3.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-qwen2.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-qwen2.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-qwen2.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-refact.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-refact.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-refact.gguf.out delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-starcoder.gguf delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-starcoder.gguf.inp delete mode 100755 ollama/llm/llama.cpp/models/ggml-vocab-starcoder.gguf.out delete mode 100755 ollama/llm/llama.cpp/mypy.ini delete mode 100755 ollama/llm/llama.cpp/pocs/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/pocs/vdot/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/pocs/vdot/q8dot.cpp delete mode 100755 ollama/llm/llama.cpp/pocs/vdot/vdot.cpp delete mode 100755 ollama/llm/llama.cpp/poetry.lock delete mode 100755 ollama/llm/llama.cpp/prompts/LLM-questions.txt delete mode 100755 ollama/llm/llama.cpp/prompts/alpaca.txt delete mode 100755 ollama/llm/llama.cpp/prompts/assistant.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat-with-baichuan.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat-with-bob.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat-with-qwen.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat-with-vicuna-v0.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat-with-vicuna-v1.txt delete mode 100755 ollama/llm/llama.cpp/prompts/chat.txt delete mode 100755 ollama/llm/llama.cpp/prompts/dan-modified.txt delete mode 100755 ollama/llm/llama.cpp/prompts/dan.txt delete mode 100755 ollama/llm/llama.cpp/prompts/mnemonics.txt delete mode 100755 ollama/llm/llama.cpp/prompts/parallel-questions.txt delete mode 100755 ollama/llm/llama.cpp/prompts/reason-act.txt delete mode 100755 ollama/llm/llama.cpp/pyproject.toml delete mode 100755 ollama/llm/llama.cpp/pyrightconfig.json delete mode 100755 ollama/llm/llama.cpp/requirements.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-all.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-compare-llama-bench.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-convert_hf_to_gguf.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-convert_hf_to_gguf_update.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-convert_legacy_llama.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-convert_llama_ggml_to_gguf.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-convert_lora_to_gguf.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-pydantic.txt delete mode 100755 ollama/llm/llama.cpp/requirements/requirements-test-tokenizer-random.txt delete mode 100755 ollama/llm/llama.cpp/scripts/build-info.sh delete mode 100755 ollama/llm/llama.cpp/scripts/check-requirements.sh delete mode 100755 ollama/llm/llama.cpp/scripts/ci-run.sh delete mode 100755 ollama/llm/llama.cpp/scripts/compare-commits.sh delete mode 100755 ollama/llm/llama.cpp/scripts/compare-llama-bench.py delete mode 100755 ollama/llm/llama.cpp/scripts/debug-test.sh delete mode 100755 ollama/llm/llama.cpp/scripts/gen-authors.sh delete mode 100755 ollama/llm/llama.cpp/scripts/gen-unicode-data.py delete mode 100755 ollama/llm/llama.cpp/scripts/get-flags.mk delete mode 100755 ollama/llm/llama.cpp/scripts/get-hellaswag.sh delete mode 100755 ollama/llm/llama.cpp/scripts/get-pg.sh delete mode 100755 ollama/llm/llama.cpp/scripts/get-wikitext-103.sh delete mode 100755 ollama/llm/llama.cpp/scripts/get-wikitext-2.sh delete mode 100755 ollama/llm/llama.cpp/scripts/get-winogrande.sh delete mode 100755 ollama/llm/llama.cpp/scripts/hf.sh delete mode 100755 ollama/llm/llama.cpp/scripts/install-oneapi.bat delete mode 100755 ollama/llm/llama.cpp/scripts/pod-llama.sh delete mode 100755 ollama/llm/llama.cpp/scripts/qnt-all.sh delete mode 100755 ollama/llm/llama.cpp/scripts/run-all-perf.sh delete mode 100755 ollama/llm/llama.cpp/scripts/run-all-ppl.sh delete mode 100755 ollama/llm/llama.cpp/scripts/run-with-preset.py delete mode 100755 ollama/llm/llama.cpp/scripts/server-llm.sh delete mode 100755 ollama/llm/llama.cpp/scripts/sync-ggml-am.sh delete mode 100755 ollama/llm/llama.cpp/scripts/sync-ggml.last delete mode 100755 ollama/llm/llama.cpp/scripts/sync-ggml.sh delete mode 100755 ollama/llm/llama.cpp/scripts/verify-checksum-models.py delete mode 100755 ollama/llm/llama.cpp/scripts/xxd.cmake delete mode 100755 ollama/llm/llama.cpp/spm-headers/ggml-alloc.h delete mode 100755 ollama/llm/llama.cpp/spm-headers/ggml-backend.h delete mode 100755 ollama/llm/llama.cpp/spm-headers/ggml-metal.h delete mode 100755 ollama/llm/llama.cpp/spm-headers/ggml.h delete mode 100755 ollama/llm/llama.cpp/spm-headers/llama.h delete mode 100755 ollama/llm/llama.cpp/src/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/src/llama-grammar.cpp delete mode 100755 ollama/llm/llama.cpp/src/llama-grammar.h delete mode 100755 ollama/llm/llama.cpp/src/llama-impl.h delete mode 100755 ollama/llm/llama.cpp/src/llama-sampling.cpp delete mode 100755 ollama/llm/llama.cpp/src/llama-sampling.h delete mode 100755 ollama/llm/llama.cpp/src/llama-vocab.cpp delete mode 100755 ollama/llm/llama.cpp/src/llama-vocab.h delete mode 100755 ollama/llm/llama.cpp/src/llama.cpp delete mode 100755 ollama/llm/llama.cpp/src/unicode-data.cpp delete mode 100755 ollama/llm/llama.cpp/src/unicode-data.h delete mode 100755 ollama/llm/llama.cpp/src/unicode.cpp delete mode 100755 ollama/llm/llama.cpp/src/unicode.h delete mode 100755 ollama/llm/llama.cpp/tests/.gitignore delete mode 100755 ollama/llm/llama.cpp/tests/CMakeLists.txt delete mode 100755 ollama/llm/llama.cpp/tests/get-model.cpp delete mode 100755 ollama/llm/llama.cpp/tests/get-model.h delete mode 100755 ollama/llm/llama.cpp/tests/run-json-schema-to-grammar.mjs delete mode 100755 ollama/llm/llama.cpp/tests/test-autorelease.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-backend-ops.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-c.c delete mode 100755 ollama/llm/llama.cpp/tests/test-chat-template.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-double-float.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-grad0.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-grammar-integration.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-grammar-parser.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-json-schema-to-grammar.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-llama-grammar.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-model-load-cancel.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-opt.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-quantize-fns.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-quantize-perf.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-rope.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-sampling.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-0.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-0.py delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-0.sh delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-1-bpe.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-1-spm.cpp delete mode 100755 ollama/llm/llama.cpp/tests/test-tokenizer-random.py delete mode 100755 ollama/llm/llm.go delete mode 100755 ollama/llm/llm_darwin_amd64.go delete mode 100755 ollama/llm/llm_darwin_arm64.go delete mode 100755 ollama/llm/llm_linux.go delete mode 100755 ollama/llm/llm_windows.go delete mode 100755 ollama/llm/memory.go delete mode 100755 ollama/llm/memory_test.go delete mode 100755 ollama/llm/patches/01-load-progress.diff delete mode 100755 ollama/llm/patches/02-clip-log.diff delete mode 100755 ollama/llm/patches/03-load_exception.diff delete mode 100755 ollama/llm/patches/04-metal.diff delete mode 100755 ollama/llm/patches/05-default-pretokenizer.diff delete mode 100755 ollama/llm/patches/06-embeddings.diff delete mode 100755 ollama/llm/patches/07-clip-unicode.diff delete mode 100755 ollama/llm/patches/08-pooling.diff delete mode 100755 ollama/llm/patches/09-lora.diff delete mode 100755 ollama/llm/patches/11-phi3-sliding-window.diff delete mode 100755 ollama/llm/payload.go delete mode 100755 ollama/llm/server.go delete mode 100755 ollama/llm/status.go delete mode 100755 ollama/macapp/.eslintrc.json delete mode 100755 ollama/macapp/.gitignore delete mode 100755 ollama/macapp/README.md delete mode 100755 ollama/macapp/assets/icon.icns delete mode 100755 ollama/macapp/assets/iconDarkTemplate.png delete mode 100755 ollama/macapp/assets/iconDarkTemplate@2x.png delete mode 100755 ollama/macapp/assets/iconDarkUpdateTemplate.png delete mode 100755 ollama/macapp/assets/iconDarkUpdateTemplate@2x.png delete mode 100755 ollama/macapp/assets/iconTemplate.png delete mode 100755 ollama/macapp/assets/iconTemplate@2x.png delete mode 100755 ollama/macapp/assets/iconUpdateTemplate.png delete mode 100755 ollama/macapp/assets/iconUpdateTemplate@2x.png delete mode 100755 ollama/macapp/forge.config.ts delete mode 100755 ollama/macapp/package-lock.json delete mode 100755 ollama/macapp/package.json delete mode 100755 ollama/macapp/postcss.config.js delete mode 100755 ollama/macapp/src/app.css delete mode 100755 ollama/macapp/src/app.tsx delete mode 100755 ollama/macapp/src/declarations.d.ts delete mode 100755 ollama/macapp/src/index.html delete mode 100755 ollama/macapp/src/index.ts delete mode 100755 ollama/macapp/src/install.ts delete mode 100755 ollama/macapp/src/ollama.svg delete mode 100755 ollama/macapp/src/preload.ts delete mode 100755 ollama/macapp/src/renderer.tsx delete mode 100755 ollama/macapp/tailwind.config.js delete mode 100755 ollama/macapp/tsconfig.json delete mode 100755 ollama/macapp/webpack.main.config.ts delete mode 100755 ollama/macapp/webpack.plugins.ts delete mode 100755 ollama/macapp/webpack.renderer.config.ts delete mode 100755 ollama/macapp/webpack.rules.ts delete mode 100755 ollama/main.go delete mode 100755 ollama/openai/openai.go delete mode 100755 ollama/openai/openai_test.go delete mode 100755 ollama/parser/parser.go delete mode 100755 ollama/parser/parser_test.go delete mode 100755 ollama/progress/bar.go delete mode 100755 ollama/progress/progress.go delete mode 100755 ollama/progress/spinner.go delete mode 100755 ollama/readline/buffer.go delete mode 100755 ollama/readline/errors.go delete mode 100755 ollama/readline/history.go delete mode 100755 ollama/readline/readline.go delete mode 100755 ollama/readline/readline_unix.go delete mode 100755 ollama/readline/readline_windows.go delete mode 100755 ollama/readline/term.go delete mode 100755 ollama/readline/term_bsd.go delete mode 100755 ollama/readline/term_linux.go delete mode 100755 ollama/readline/term_windows.go delete mode 100755 ollama/readline/types.go delete mode 100755 ollama/scripts/build.sh delete mode 100755 ollama/scripts/build_darwin.sh delete mode 100755 ollama/scripts/build_docker.sh delete mode 100755 ollama/scripts/build_linux.sh delete mode 100755 ollama/scripts/build_remote.py delete mode 100755 ollama/scripts/build_windows.ps1 delete mode 100755 ollama/scripts/install.sh delete mode 100755 ollama/scripts/publish.sh delete mode 100755 ollama/scripts/push_docker.sh delete mode 100755 ollama/scripts/rh_linux_deps.sh delete mode 100755 ollama/scripts/tag_latest.sh delete mode 100755 ollama/server/auth.go delete mode 100755 ollama/server/download.go delete mode 100755 ollama/server/fixblobs.go delete mode 100755 ollama/server/fixblobs_test.go delete mode 100755 ollama/server/images.go delete mode 100755 ollama/server/layer.go delete mode 100755 ollama/server/manifest.go delete mode 100755 ollama/server/manifest_test.go delete mode 100755 ollama/server/model.go delete mode 100755 ollama/server/model_test.go delete mode 100755 ollama/server/modelpath.go delete mode 100755 ollama/server/modelpath_test.go delete mode 100755 ollama/server/prompt.go delete mode 100755 ollama/server/prompt_test.go delete mode 100755 ollama/server/routes.go delete mode 100755 ollama/server/routes_create_test.go delete mode 100755 ollama/server/routes_delete_test.go delete mode 100755 ollama/server/routes_generate_test.go delete mode 100755 ollama/server/routes_list_test.go delete mode 100755 ollama/server/routes_test.go delete mode 100755 ollama/server/sched.go delete mode 100755 ollama/server/sched_test.go delete mode 100755 ollama/server/sparse_common.go delete mode 100755 ollama/server/sparse_windows.go delete mode 100755 ollama/server/testdata/tools/command-r-plus.gotmpl delete mode 100755 ollama/server/testdata/tools/command-r-plus.out delete mode 100755 ollama/server/testdata/tools/firefunction.gotmpl delete mode 100755 ollama/server/testdata/tools/firefunction.out delete mode 100755 ollama/server/testdata/tools/llama3-groq-tool-use.gotmpl delete mode 100755 ollama/server/testdata/tools/llama3-groq-tool-use.out delete mode 100755 ollama/server/testdata/tools/messages.json delete mode 100755 ollama/server/testdata/tools/mistral.gotmpl delete mode 100755 ollama/server/testdata/tools/mistral.out delete mode 100755 ollama/server/testdata/tools/tools.json delete mode 100755 ollama/server/testdata/tools/xlam.gotmpl delete mode 100755 ollama/server/testdata/tools/xlam.out delete mode 100755 ollama/server/upload.go delete mode 100755 ollama/template/alfred.gotmpl delete mode 100755 ollama/template/alfred.json delete mode 100755 ollama/template/alpaca.gotmpl delete mode 100755 ollama/template/alpaca.json delete mode 100755 ollama/template/chatml.gotmpl delete mode 100755 ollama/template/chatml.json delete mode 100755 ollama/template/chatqa.gotmpl delete mode 100755 ollama/template/chatqa.json delete mode 100755 ollama/template/codellama-70b-instruct.gotmpl delete mode 100755 ollama/template/codellama-70b-instruct.json delete mode 100755 ollama/template/falcon-instruct.gotmpl delete mode 100755 ollama/template/falcon-instruct.json delete mode 100755 ollama/template/gemma-instruct.gotmpl delete mode 100755 ollama/template/gemma-instruct.json delete mode 100755 ollama/template/granite-instruct.gotmpl delete mode 100755 ollama/template/granite-instruct.json delete mode 100755 ollama/template/index.json delete mode 100755 ollama/template/llama2-chat.gotmpl delete mode 100755 ollama/template/llama2-chat.json delete mode 100755 ollama/template/llama3-instruct.gotmpl delete mode 100755 ollama/template/llama3-instruct.json delete mode 100755 ollama/template/magicoder.gotmpl delete mode 100755 ollama/template/magicoder.json delete mode 100755 ollama/template/mistral-instruct.gotmpl delete mode 100755 ollama/template/mistral-instruct.json delete mode 100755 ollama/template/openchat.gotmpl delete mode 100755 ollama/template/openchat.json delete mode 100755 ollama/template/phi-3.gotmpl delete mode 100755 ollama/template/phi-3.json delete mode 100755 ollama/template/solar-instruct.gotmpl delete mode 100755 ollama/template/solar-instruct.json delete mode 100755 ollama/template/starcoder2-instruct.gotmpl delete mode 100755 ollama/template/starcoder2-instruct.json delete mode 100755 ollama/template/template.go delete mode 100755 ollama/template/template_test.go delete mode 100755 ollama/template/testdata/alfred.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/alfred.gotmpl/user delete mode 100755 ollama/template/testdata/alfred.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/alpaca.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/alpaca.gotmpl/user delete mode 100755 ollama/template/testdata/alpaca.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/chatml.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/chatml.gotmpl/user delete mode 100755 ollama/template/testdata/chatml.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/chatqa.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/chatqa.gotmpl/user delete mode 100755 ollama/template/testdata/chatqa.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/codellama-70b-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/codellama-70b-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/codellama-70b-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/falcon-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/falcon-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/falcon-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/gemma-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/gemma-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/gemma-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/granite-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/granite-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/granite-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/llama2-chat.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/llama2-chat.gotmpl/user delete mode 100755 ollama/template/testdata/llama2-chat.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/llama3-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/llama3-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/llama3-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/magicoder.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/magicoder.gotmpl/user delete mode 100755 ollama/template/testdata/magicoder.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/mistral-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/mistral-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/mistral-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/openchat.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/openchat.gotmpl/user delete mode 100755 ollama/template/testdata/openchat.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/phi-3.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/phi-3.gotmpl/user delete mode 100755 ollama/template/testdata/phi-3.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/solar-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/solar-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/solar-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/starcoder2-instruct.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/starcoder2-instruct.gotmpl/user delete mode 100755 ollama/template/testdata/starcoder2-instruct.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/templates.jsonl delete mode 100755 ollama/template/testdata/vicuna.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/vicuna.gotmpl/user delete mode 100755 ollama/template/testdata/vicuna.gotmpl/user-assistant-user delete mode 100755 ollama/template/testdata/zephyr.gotmpl/system-user-assistant-user delete mode 100755 ollama/template/testdata/zephyr.gotmpl/user delete mode 100755 ollama/template/testdata/zephyr.gotmpl/user-assistant-user delete mode 100755 ollama/template/vicuna.gotmpl delete mode 100755 ollama/template/vicuna.json delete mode 100755 ollama/template/zephyr.gotmpl delete mode 100755 ollama/template/zephyr.json delete mode 100755 ollama/types/errtypes/errtypes.go delete mode 100755 ollama/types/model/name.go delete mode 100755 ollama/types/model/name_test.go delete mode 100755 ollama/types/model/testdata/fuzz/FuzzName/d37463aa416f6bab delete mode 100755 ollama/util/bufioutil/buffer_seeker.go delete mode 100755 ollama/util/bufioutil/buffer_seeker_test.go delete mode 100755 ollama/version/version.go diff --git a/ollama/.dockerignore b/ollama/.dockerignore deleted file mode 100755 index 43f2e07..0000000 --- a/ollama/.dockerignore +++ /dev/null @@ -1,9 +0,0 @@ -.vscode -ollama -app -macapp -dist -llm/llama.cpp -.env -.cache -test_data diff --git a/ollama/.gitattributes b/ollama/.gitattributes deleted file mode 100755 index f1c8bcb..0000000 --- a/ollama/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -llm/ext_server/* linguist-vendored -* text=auto -*.go text eol=lf diff --git a/ollama/.github/ISSUE_TEMPLATE/10_bug_report.yml b/ollama/.github/ISSUE_TEMPLATE/10_bug_report.yml deleted file mode 100755 index d0c79bc..0000000 --- a/ollama/.github/ISSUE_TEMPLATE/10_bug_report.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Bug report -labels: [bug] -description: Something isn't working right. -body: - - type: textarea - id: description - attributes: - label: What is the issue? - description: What happened? What did you expect to happen? - validations: - required: true - - type: dropdown - id: os - attributes: - label: OS - description: Which operating system are you using? - multiple: true - options: - - Linux - - macOS - - Windows - - Docker - - WSL2 - validations: - required: false - - type: dropdown - id: gpu - attributes: - label: GPU - description: Which GPU are you using? - multiple: true - options: - - Nvidia - - AMD - - Intel - - Apple - - Other - validations: - required: false - - type: dropdown - id: cpu - attributes: - label: CPU - description: Which CPU are you using? - multiple: true - options: - - Intel - - AMD - - Apple - - Other - validations: - required: false - - type: input - id: version - attributes: - label: Ollama version - description: What version of Ollama are you using? (`ollama --version`) - placeholder: e.g., 0.1.32 - validations: - required: false diff --git a/ollama/.github/ISSUE_TEMPLATE/20_feature_request.md b/ollama/.github/ISSUE_TEMPLATE/20_feature_request.md deleted file mode 100755 index e899721..0000000 --- a/ollama/.github/ISSUE_TEMPLATE/20_feature_request.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -name: Feature request -about: Request a new feature -labels: feature request ---- - diff --git a/ollama/.github/ISSUE_TEMPLATE/30_model_request.md b/ollama/.github/ISSUE_TEMPLATE/30_model_request.md deleted file mode 100755 index c705a5f..0000000 --- a/ollama/.github/ISSUE_TEMPLATE/30_model_request.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -name: Model request -about: Request support for a new model to be added to Ollama -labels: model request ---- \ No newline at end of file diff --git a/ollama/.github/ISSUE_TEMPLATE/config.yml b/ollama/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100755 index 70d9aa3..0000000 --- a/ollama/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -blank_issues_enabled: true -contact_links: - - name: Help - url: https://discord.com/invite/ollama - about: Please join our Discord server for help using Ollama - - name: Troubleshooting - url: https://github.com/ollama/ollama/blob/main/docs/faq.md#faq - about: See the FAQ for common issues and solutions diff --git a/ollama/.github/workflows/latest.yaml b/ollama/.github/workflows/latest.yaml deleted file mode 100755 index 4d47dd3..0000000 --- a/ollama/.github/workflows/latest.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: latest - -on: - release: - types: [released] - -jobs: - update-latest: - environment: release - runs-on: linux - steps: - - uses: actions/checkout@v4 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKER_USER }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Tag images as latest - env: - PUSH: "1" - shell: bash - run: | - export "VERSION=${GITHUB_REF_NAME#v}" - ./scripts/tag_latest.sh diff --git a/ollama/.github/workflows/release.yaml b/ollama/.github/workflows/release.yaml deleted file mode 100755 index f0c6db5..0000000 --- a/ollama/.github/workflows/release.yaml +++ /dev/null @@ -1,480 +0,0 @@ -name: release - -on: - push: - tags: - - 'v*' - -jobs: - # Full build of the Mac assets - build-darwin: - runs-on: macos-12 - environment: release - steps: - - uses: actions/checkout@v4 - - name: Set Version - shell: bash - run: | - echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - echo "RELEASE_VERSION=$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" >> $GITHUB_ENV - - name: key - env: - MACOS_SIGNING_KEY: ${{ secrets.MACOS_SIGNING_KEY }} - MACOS_SIGNING_KEY_PASSWORD: ${{ secrets.MACOS_SIGNING_KEY_PASSWORD }} - run: | - echo $MACOS_SIGNING_KEY | base64 --decode > certificate.p12 - security create-keychain -p password build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p password build.keychain - security import certificate.p12 -k build.keychain -P $MACOS_SIGNING_KEY_PASSWORD -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k password build.keychain - security set-keychain-settings -lut 3600 build.keychain - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - name: Build Darwin - env: - APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} - APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} - APPLE_TEAM_ID: ${{ vars.APPLE_TEAM_ID }} - APPLE_ID: ${{ vars.APPLE_ID }} - SDKROOT: /Applications/Xcode_13.4.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk - DEVELOPER_DIR: /Applications/Xcode_13.4.1.app/Contents/Developer - run: | - ./scripts/build_darwin.sh - - - uses: actions/upload-artifact@v4 - with: - name: dist-darwin - path: | - dist/*arwin* - !dist/*-cov - - # Windows builds take a long time to both install the dependencies and build, so parallelize - # CPU generation step - generate-windows-cpu: - environment: release - runs-on: windows - env: - KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} - steps: - - uses: actions/checkout@v4 - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - uses: 'google-github-actions/auth@v2' - with: - project_id: 'ollama' - credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' - - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt - - name: install Windows SDK 8.1 to get signtool - run: | - $ErrorActionPreference = "Stop" - write-host "downloading SDK" - Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" - Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait - write-host "Win SDK 8.1 installed" - gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' - - name: install signing plugin - run: | - $ErrorActionPreference = "Stop" - write-host "downloading plugin" - Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" - Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ - write-host "Installing plugin" - & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet - write-host "plugin installed" - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - run: go get ./... - - run: | - $gopath=(get-command go).source | split-path -parent - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$env:PATH" - go generate -x ./... - name: go generate - - uses: actions/upload-artifact@v4 - with: - name: generate-windows-cpu - path: | - llm/build/**/bin/* - llm/build/**/*.a - dist/windows-amd64/** - - # ROCm generation step - generate-windows-rocm: - environment: release - runs-on: windows - env: - KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} - steps: - - uses: actions/checkout@v4 - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - uses: 'google-github-actions/auth@v2' - with: - project_id: 'ollama' - credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' - - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt - - name: install Windows SDK 8.1 to get signtool - run: | - $ErrorActionPreference = "Stop" - write-host "downloading SDK" - Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" - Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait - write-host "Win SDK 8.1 installed" - gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' - - name: install signing plugin - run: | - $ErrorActionPreference = "Stop" - write-host "downloading plugin" - Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" - Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ - write-host "Installing plugin" - & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet - write-host "plugin installed" - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - name: 'Install ROCm' - run: | - $ErrorActionPreference = "Stop" - write-host "downloading AMD HIP Installer" - Invoke-WebRequest -Uri "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-24.Q3-WinSvr2022-For-HIP.exe" -OutFile "${env:RUNNER_TEMP}\rocm-install.exe" - write-host "Installing AMD HIP" - Start-Process "${env:RUNNER_TEMP}\rocm-install.exe" -ArgumentList '-install' -NoNewWindow -Wait - write-host "Completed AMD HIP" - - name: 'Verify ROCm' - run: | - & 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' --version - - run: go get ./... - - run: | - $gopath=(get-command go).source | split-path -parent - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$env:PATH" - $env:OLLAMA_SKIP_CPU_GENERATE="1" - $env:HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path) - go generate -x ./... - name: go generate - - name: 'gather rocm dependencies' - run: | - $HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path) - md "dist\deps\bin\rocblas\library" - cp "${HIP_PATH}\bin\hipblas.dll" "dist\deps\bin\" - cp "${HIP_PATH}\bin\rocblas.dll" "dist\deps\bin\" - cp "${HIP_PATH}\bin\rocblas\library\*" "dist\deps\bin\rocblas\library\" - - uses: actions/upload-artifact@v4 - with: - name: generate-windows-rocm - path: | - llm/build/**/bin/* - dist/windows-amd64/** - - uses: actions/upload-artifact@v4 - with: - name: windows-rocm-deps - path: dist/deps/* - - # CUDA generation step - generate-windows-cuda: - environment: release - runs-on: windows - env: - KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} - steps: - - uses: actions/checkout@v4 - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - uses: 'google-github-actions/auth@v2' - with: - project_id: 'ollama' - credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' - - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt - - name: install Windows SDK 8.1 to get signtool - run: | - $ErrorActionPreference = "Stop" - write-host "downloading SDK" - Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" - Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait - write-host "Win SDK 8.1 installed" - gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' - - name: install signing plugin - run: | - $ErrorActionPreference = "Stop" - write-host "downloading plugin" - Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" - Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ - write-host "Installing plugin" - & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet - write-host "plugin installed" - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - name: 'Install CUDA' - run: | - $ErrorActionPreference = "Stop" - write-host "downloading CUDA Installer" - Invoke-WebRequest -Uri "https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.89_win10.exe" -OutFile "${env:RUNNER_TEMP}\cuda-install.exe" - write-host "Installing CUDA" - Start-Process "${env:RUNNER_TEMP}\cuda-install.exe" -ArgumentList '-s' -NoNewWindow -Wait - write-host "Completed CUDA" - $cudaPath=((resolve-path "c:\Program Files\NVIDIA*\CUDA\v*\bin\nvcc.exe")[0].path | split-path | split-path) - $cudaVer=($cudaPath | split-path -leaf ) -replace 'v(\d+).(\d+)', '$1_$2' - echo "$cudaPath\bin" >> $env:GITHUB_PATH - echo "CUDA_PATH=$cudaPath" >> $env:GITHUB_ENV - echo "CUDA_PATH_V${cudaVer}=$cudaPath" >> $env:GITHUB_ENV - echo "CUDA_PATH_VX_Y=CUDA_PATH_V${cudaVer}" >> $env:GITHUB_ENV - - name: 'Verify CUDA' - run: nvcc -V - - run: go get ./... - - name: go generate - run: | - $gopath=(get-command go).source | split-path -parent - $cudabin=(get-command nvcc).source | split-path - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$cudabin;$env:PATH" - $env:OLLAMA_SKIP_CPU_GENERATE="1" - go generate -x ./... - - name: 'gather cuda dependencies' - run: | - $NVIDIA_DIR=(resolve-path 'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\*\bin\')[0] - md "dist\deps" - cp "${NVIDIA_DIR}\cudart64_*.dll" "dist\deps\" - cp "${NVIDIA_DIR}\cublas64_*.dll" "dist\deps\" - cp "${NVIDIA_DIR}\cublasLt64_*.dll" "dist\deps\" - - uses: actions/upload-artifact@v4 - with: - name: generate-windows-cuda - path: | - llm/build/**/bin/* - dist/windows-amd64/** - - uses: actions/upload-artifact@v4 - with: - name: windows-cuda-deps - path: dist/deps/* - - # Import the prior generation steps and build the final windows assets - build-windows: - environment: release - runs-on: windows - needs: - - generate-windows-cuda - - generate-windows-rocm - - generate-windows-cpu - env: - KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - uses: 'google-github-actions/auth@v2' - with: - project_id: 'ollama' - credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' - - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt - - name: install Windows SDK 8.1 to get signtool - run: | - $ErrorActionPreference = "Stop" - write-host "downloading SDK" - Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" - Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait - write-host "Win SDK 8.1 installed" - gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' - - name: install signing plugin - run: | - $ErrorActionPreference = "Stop" - write-host "downloading plugin" - Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" - Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ - write-host "Installing plugin" - & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet - write-host "plugin installed" - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - run: go get - - uses: actions/download-artifact@v4 - with: - name: generate-windows-cpu - - uses: actions/download-artifact@v4 - with: - name: generate-windows-cuda - - uses: actions/download-artifact@v4 - with: - name: windows-cuda-deps - - uses: actions/download-artifact@v4 - with: - name: windows-rocm-deps - - uses: actions/download-artifact@v4 - with: - name: generate-windows-rocm - - run: dir llm/build - - run: | - $gopath=(get-command go).source | split-path -parent - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$env:PATH" - $env:OLLAMA_SKIP_GENERATE="1" - & .\scripts\build_windows.ps1 - - uses: actions/upload-artifact@v4 - with: - name: dist-windows - path: | - dist/OllamaSetup.exe - dist/ollama-windows-*.zip - - # Linux x86 assets built using the container based build - build-linux-amd64: - environment: release - runs-on: linux - env: - OLLAMA_SKIP_MANIFEST_CREATE: '1' - BUILD_ARCH: amd64 - PUSH: '1' - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKER_USER }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - run: | - ./scripts/build_linux.sh - ./scripts/build_docker.sh - mv dist/deps/* dist/ - - uses: actions/upload-artifact@v4 - with: - name: dist-linux-amd64 - path: | - dist/*linux* - !dist/*-cov - - # Linux ARM assets built using the container based build - # (at present, docker isn't pre-installed on arm ubunutu images) - build-linux-arm64: - environment: release - runs-on: linux-arm64 - env: - OLLAMA_SKIP_MANIFEST_CREATE: '1' - BUILD_ARCH: arm64 - PUSH: '1' - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set Version - shell: bash - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - name: 'Install Docker' - run: | - # Add Docker's official GPG key: - env - uname -a - sudo apt-get update - sudo apt-get install -y ca-certificates curl - sudo install -m 0755 -d /etc/apt/keyrings - sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc - sudo chmod a+r /etc/apt/keyrings/docker.asc - - # Add the repository to Apt sources: - echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ - $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt-get update - sudo apt-get install -y docker-ce docker-ce-cli containerd.io - sudo usermod -aG docker $USER - sudo apt-get install acl - sudo setfacl --modify user:$USER:rw /var/run/docker.sock - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKER_USER }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - run: | - ./scripts/build_linux.sh - ./scripts/build_docker.sh - - uses: actions/upload-artifact@v4 - with: - name: dist-linux-arm64 - path: | - dist/*linux* - !dist/*-cov - - # Aggregate all the assets and ship a release - release: - needs: - - build-darwin - - build-windows - - build-linux-amd64 - - build-linux-arm64 - runs-on: linux - environment: release - permissions: - contents: write - env: - OLLAMA_SKIP_IMAGE_BUILD: '1' - PUSH: '1' - GH_TOKEN: ${{ github.token }} - steps: - - uses: actions/checkout@v4 - - name: Set Version - shell: bash - run: | - echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - echo "RELEASE_VERSION=$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" >> $GITHUB_ENV - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKER_USER }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - run: ./scripts/build_docker.sh - - name: Retrieve built artifact - uses: actions/download-artifact@v4 - with: - path: dist - pattern: dist-* - merge-multiple: true - - run: | - ls -lh dist/ - (cd dist; sha256sum * > sha256sum.txt) - cat dist/sha256sum.txt - - name: Create or update Release - run: | - echo "Looking for existing release for ${{ env.RELEASE_VERSION }}" - OLD_TAG=$(gh release ls --json name,tagName | jq -r ".[] | select(.name == \"${{ env.RELEASE_VERSION }}\") | .tagName") - if [ -n "$OLD_TAG" ]; then - echo "Updating release ${{ env.RELEASE_VERSION }} to point to new tag ${GITHUB_REF_NAME}" - gh release edit ${OLD_TAG} --tag ${GITHUB_REF_NAME} - else - echo "Creating new release ${{ env.RELEASE_VERSION }} pointing to tag ${GITHUB_REF_NAME}" - gh release create ${GITHUB_REF_NAME} \ - --title ${{ env.RELEASE_VERSION }} \ - --draft \ - --generate-notes \ - --prerelease - fi - echo "Uploading artifacts for tag ${GITHUB_REF_NAME}" - gh release upload ${GITHUB_REF_NAME} dist/* --clobber diff --git a/ollama/.github/workflows/test.yaml b/ollama/.github/workflows/test.yaml deleted file mode 100755 index a57d45f..0000000 --- a/ollama/.github/workflows/test.yaml +++ /dev/null @@ -1,323 +0,0 @@ -name: test - -concurrency: - # For PRs, later CI runs preempt previous ones. e.g. a force push on a PR - # cancels running CI jobs and starts all new ones. - # - # For non-PR pushes, concurrency.group needs to be unique for every distinct - # CI run we want to have happen. Use run_id, which in practice means all - # non-PR CI runs will be allowed to run without preempting each other. - group: ${{ github.workflow }}-$${{ github.pull_request.number || github.run_id }} - cancel-in-progress: true - -on: - pull_request: - paths: - - '**/*' - - '!docs/**' - - '!README.md' - -jobs: - changes: - runs-on: ubuntu-latest - outputs: - GENERATE: ${{ steps.changes.outputs.GENERATE }} - GENERATE_CUDA: ${{ steps.changes.outputs.GENERATE_CUDA }} - GENERATE_ROCM: ${{ steps.changes.outputs.GENERATE_ROCM }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - id: changes - run: | - changed() { - git diff-tree -r --no-commit-id --name-only \ - $(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) \ - ${{ github.event.pull_request.head.sha }} \ - | xargs python3 -c "import sys; from pathlib import Path; print(any(Path(x).match(glob) for x in sys.argv[1:] for glob in '$*'.split(' ')))" - } - - { - echo GENERATE=$(changed 'llm/llama.cpp' 'llm/patches/**' 'llm/ext_server/**' 'llm/generate/**') - echo GENERATE_CUDA=$(changed 'llm/llama.cpp' 'llm/patches/**' 'llm/ext_server/**' 'llm/generate/**') - echo GENERATE_ROCM=$(changed 'llm/llama.cpp' 'llm/patches/**' 'llm/ext_server/**' 'llm/generate/**') - } >>$GITHUB_OUTPUT - - generate: - needs: [changes] - if: ${{ needs.changes.outputs.GENERATE == 'True' }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-2019] - arch: [amd64, arm64] - exclude: - - os: ubuntu-latest - arch: arm64 - - os: windows-2019 - arch: arm64 - runs-on: ${{ matrix.os }} - env: - GOARCH: ${{ matrix.arch }} - CGO_ENABLED: '1' - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - run: go get ./... - - run: | - $gopath=(get-command go).source | split-path -parent - $gccpath=(get-command gcc).source | split-path -parent - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$gccpath;$env:PATH" - echo $env:PATH - go generate -x ./... - if: ${{ startsWith(matrix.os, 'windows-') }} - name: 'Windows Go Generate' - - run: go generate -x ./... - if: ${{ ! startsWith(matrix.os, 'windows-') }} - name: 'Unix Go Generate' - - run: go build . - - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.os }}-${{ matrix.arch }}-libraries - path: | - llm/build/**/bin/* - llm/build/**/*.a - generate-cuda: - needs: [changes] - if: ${{ needs.changes.outputs.GENERATE_CUDA == 'True' }} - strategy: - matrix: - cuda-version: - - '11.8.0' - runs-on: linux - container: nvidia/cuda:${{ matrix.cuda-version }}-devel-ubuntu20.04 - steps: - - run: | - apt-get update && apt-get install -y git build-essential curl - curl -fsSL https://github.com/Kitware/CMake/releases/download/v3.28.1/cmake-3.28.1-linux-x86_64.tar.gz \ - | tar -zx -C /usr --strip-components 1 - env: - DEBIAN_FRONTEND: noninteractive - - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - cache: true - - run: go get ./... - - run: | - git config --global --add safe.directory /__w/ollama/ollama - go generate -x ./... - env: - OLLAMA_SKIP_CPU_GENERATE: '1' - - uses: actions/upload-artifact@v4 - with: - name: cuda-${{ matrix.cuda-version }}-libraries - path: | - llm/build/**/bin/* - dist/windows-amd64/** - generate-rocm: - needs: [changes] - if: ${{ needs.changes.outputs.GENERATE_ROCM == 'True' }} - strategy: - matrix: - rocm-version: - - '6.1.2' - runs-on: linux - container: rocm/dev-ubuntu-20.04:${{ matrix.rocm-version }} - steps: - - run: | - apt-get update && apt-get install -y git build-essential curl rocm-libs - curl -fsSL https://github.com/Kitware/CMake/releases/download/v3.28.1/cmake-3.28.1-linux-x86_64.tar.gz \ - | tar -zx -C /usr --strip-components 1 - env: - DEBIAN_FRONTEND: noninteractive - - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version-file: go.mod - cache: true - - run: go get ./... - - run: | - git config --global --add safe.directory /__w/ollama/ollama - go generate -x ./... - env: - OLLAMA_SKIP_CPU_GENERATE: '1' - - uses: actions/upload-artifact@v4 - with: - name: rocm-${{ matrix.rocm-version }}-libraries - path: | - llm/build/**/bin/* - dist/windows-amd64/** - - # ROCm generation step - generate-windows-rocm: - needs: [changes] - if: ${{ needs.changes.outputs.GENERATE_ROCM == 'True' }} - runs-on: windows - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - name: 'Install ROCm' - run: | - $ErrorActionPreference = "Stop" - write-host "downloading AMD HIP Installer" - Invoke-WebRequest -Uri "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-24.Q3-WinSvr2022-For-HIP.exe" -OutFile "${env:RUNNER_TEMP}\rocm-install.exe" - write-host "Installing AMD HIP" - Start-Process "${env:RUNNER_TEMP}\rocm-install.exe" -ArgumentList '-install' -NoNewWindow -Wait - write-host "Completed AMD HIP" - - name: 'Verify ROCm' - run: | - & 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' --version - - run: go get ./... - - run: | - $gopath=(get-command go).source | split-path -parent - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$env:PATH" - $env:OLLAMA_SKIP_CPU_GENERATE="1" - $env:HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path) - go generate -x ./... - name: go generate - env: - OLLAMA_SKIP_CPU_GENERATE: '1' - # TODO - do we need any artifacts? - - # CUDA generation step - generate-windows-cuda: - needs: [changes] - if: ${{ needs.changes.outputs.GENERATE_CUDA == 'True' }} - runs-on: windows - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - name: 'Install CUDA' - run: | - $ErrorActionPreference = "Stop" - write-host "downloading CUDA Installer" - Invoke-WebRequest -Uri "https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.89_win10.exe" -OutFile "${env:RUNNER_TEMP}\cuda-install.exe" - write-host "Installing CUDA" - Start-Process "${env:RUNNER_TEMP}\cuda-install.exe" -ArgumentList '-s' -NoNewWindow -Wait - write-host "Completed CUDA" - $cudaPath=((resolve-path "c:\Program Files\NVIDIA*\CUDA\v*\bin\nvcc.exe")[0].path | split-path | split-path) - $cudaVer=($cudaPath | split-path -leaf ) -replace 'v(\d+).(\d+)', '$1_$2' - echo "$cudaPath\bin" >> $env:GITHUB_PATH - echo "CUDA_PATH=$cudaPath" >> $env:GITHUB_ENV - echo "CUDA_PATH_V${cudaVer}=$cudaPath" >> $env:GITHUB_ENV - echo "CUDA_PATH_VX_Y=CUDA_PATH_V${cudaVer}" >> $env:GITHUB_ENV - - name: 'Verify CUDA' - run: nvcc -V - - run: go get ./... - - name: go generate - run: | - $gopath=(get-command go).source | split-path -parent - $cudabin=(get-command nvcc).source | split-path - & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" - cd $env:GITHUB_WORKSPACE - $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" - $env:PATH="$gopath;$cudabin;$env:PATH" - $env:OLLAMA_SKIP_CPU_GENERATE="1" - go generate -x ./... - env: - OLLAMA_SKIP_CPU_GENERATE: '1' - # TODO - do we need any artifacts? - - lint: - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-2019] - arch: [amd64, arm64] - exclude: - - os: ubuntu-latest - arch: arm64 - - os: windows-2019 - arch: arm64 - - os: macos-latest - arch: amd64 - runs-on: ${{ matrix.os }} - env: - GOARCH: ${{ matrix.arch }} - CGO_ENABLED: '1' - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: false - - run: | - case ${{ matrix.arch }} in - amd64) echo ARCH=x86_64 ;; - arm64) echo ARCH=arm64 ;; - esac >>$GITHUB_ENV - shell: bash - - run: | - mkdir -p llm/build/linux/$ARCH/stub/bin - touch llm/build/linux/$ARCH/stub/bin/ollama_llama_server - if: ${{ startsWith(matrix.os, 'ubuntu-') }} - - run: | - mkdir -p llm/build/darwin/$ARCH/stub/bin - touch llm/build/darwin/$ARCH/stub/bin/ollama_llama_server - if: ${{ startsWith(matrix.os, 'macos-') }} - - uses: golangci/golangci-lint-action@v6 - with: - args: --timeout 8m0s -v - test: - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-2019] - arch: [amd64] - exclude: - - os: ubuntu-latest - arch: arm64 - - os: windows-2019 - arch: arm64 - runs-on: ${{ matrix.os }} - env: - GOARCH: ${{ matrix.arch }} - CGO_ENABLED: '1' - OLLAMA_CPU_TARGET: 'static' - OLLAMA_SKIP_CPU_GENERATE: '1' - OLLAMA_SKIP_METAL_GENERATE: '1' - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - uses: actions/setup-go@v5 - with: - go-version: "stable" - cache: true - - run: | - case ${{ matrix.arch }} in - amd64) echo ARCH=x86_64 ;; - arm64) echo ARCH=arm64 ;; - esac >>$GITHUB_ENV - shell: bash - - run: | - mkdir -p llm/build/linux/$ARCH/stub/bin - touch llm/build/linux/$ARCH/stub/bin/ollama_llama_server - if: ${{ startsWith(matrix.os, 'ubuntu-') }} - - run: | - mkdir -p llm/build/darwin/$ARCH/stub/bin - touch llm/build/darwin/$ARCH/stub/bin/ollama_llama_server - if: ${{ startsWith(matrix.os, 'macos-') }} - shell: bash - - run: go generate ./... - - run: go build - - run: go test -v ./... - - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.os }}-binaries - path: ollama diff --git a/ollama/.gitignore b/ollama/.gitignore deleted file mode 100755 index 0d826ab..0000000 --- a/ollama/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -.DS_Store -.vscode -.env -.venv -.swp -dist -ollama -ggml-metal.metal -.cache -*.exe -.idea -test_data -*.crt -llm/build -__debug_bin* \ No newline at end of file diff --git a/ollama/.gitmodules b/ollama/.gitmodules deleted file mode 100755 index b92f645..0000000 --- a/ollama/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "llama.cpp"] - path = llm/llama.cpp - url = https://github.com/ggerganov/llama.cpp.git - shallow = true \ No newline at end of file diff --git a/ollama/.golangci.yaml b/ollama/.golangci.yaml deleted file mode 100755 index c2c8b52..0000000 --- a/ollama/.golangci.yaml +++ /dev/null @@ -1,44 +0,0 @@ -run: - timeout: 5m -linters: - enable: - - asasalint - - bidichk - - bodyclose - - containedctx - - contextcheck - - errcheck - - exportloopref - - gci - - gocheckcompilerdirectives - - gofmt - - gofumpt - - gosimple - - govet - - ineffassign - - intrange - - makezero - - misspell - - nilerr - - nolintlint - - nosprintfhostport - - staticcheck - - tenv - - testifylint - - unconvert - - unused - - usestdlibvars - - wastedassign - - whitespace -linters-settings: - gci: - sections: [standard, default, localmodule] -severity: - default-severity: error - rules: - - linters: - - gofmt - - goimports - - intrange - - usestdlibvars - severity: info diff --git a/ollama/.prettierrc.json b/ollama/.prettierrc.json deleted file mode 100755 index 0b3312d..0000000 --- a/ollama/.prettierrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "trailingComma": "es5", - "tabWidth": 2, - "useTabs": false, - "semi": false, - "singleQuote": true, - "jsxSingleQuote": true, - "printWidth": 120, - "arrowParens": "avoid" -} diff --git a/ollama/Dockerfile b/ollama/Dockerfile deleted file mode 100755 index c8efdd8..0000000 --- a/ollama/Dockerfile +++ /dev/null @@ -1,144 +0,0 @@ -ARG GOLANG_VERSION=1.22.5 -ARG CMAKE_VERSION=3.22.1 -# this CUDA_VERSION corresponds with the one specified in docs/gpu.md -ARG CUDA_VERSION=11.3.1 -ARG ROCM_VERSION=6.1.2 - -# Copy the minimal context we need to run the generate scripts -FROM scratch AS llm-code -COPY .git .git -COPY .gitmodules .gitmodules -COPY llm llm - -FROM --platform=linux/amd64 nvidia/cuda:$CUDA_VERSION-devel-centos7 AS cuda-build-amd64 -ARG CMAKE_VERSION -COPY ./scripts/rh_linux_deps.sh / -RUN CMAKE_VERSION=${CMAKE_VERSION} sh /rh_linux_deps.sh -ENV PATH /opt/rh/devtoolset-10/root/usr/bin:$PATH -COPY --from=llm-code / /go/src/github.com/ollama/ollama/ -WORKDIR /go/src/github.com/ollama/ollama/llm/generate -ARG CGO_CFLAGS -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_SKIP_CPU_GENERATE=1 sh gen_linux.sh - -FROM --platform=linux/arm64 nvidia/cuda:$CUDA_VERSION-devel-rockylinux8 AS cuda-build-arm64 -ARG CMAKE_VERSION -COPY ./scripts/rh_linux_deps.sh / -RUN CMAKE_VERSION=${CMAKE_VERSION} sh /rh_linux_deps.sh -ENV PATH /opt/rh/gcc-toolset-10/root/usr/bin:$PATH -COPY --from=llm-code / /go/src/github.com/ollama/ollama/ -WORKDIR /go/src/github.com/ollama/ollama/llm/generate -ARG CGO_CFLAGS -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_SKIP_CPU_GENERATE=1 sh gen_linux.sh - -FROM --platform=linux/amd64 rocm/dev-centos-7:${ROCM_VERSION}-complete AS rocm-build-amd64 -ARG CMAKE_VERSION -COPY ./scripts/rh_linux_deps.sh / -RUN CMAKE_VERSION=${CMAKE_VERSION} sh /rh_linux_deps.sh -ENV PATH /opt/rh/devtoolset-10/root/usr/bin:$PATH -ENV LIBRARY_PATH /opt/amdgpu/lib64 -COPY --from=llm-code / /go/src/github.com/ollama/ollama/ -WORKDIR /go/src/github.com/ollama/ollama/llm/generate -ARG CGO_CFLAGS -ARG AMDGPU_TARGETS -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_SKIP_CPU_GENERATE=1 sh gen_linux.sh -RUN mkdir /tmp/scratch && \ - for dep in $(zcat /go/src/github.com/ollama/ollama/llm/build/linux/x86_64/rocm*/bin/deps.txt.gz) ; do \ - cp ${dep} /tmp/scratch/ || exit 1 ; \ - done && \ - (cd /opt/rocm/lib && tar cf - rocblas/library) | (cd /tmp/scratch/ && tar xf - ) && \ - mkdir -p /go/src/github.com/ollama/ollama/dist/deps/ && \ - (cd /tmp/scratch/ && tar czvf /go/src/github.com/ollama/ollama/dist/deps/ollama-linux-amd64-rocm.tgz . ) - - -FROM --platform=linux/amd64 centos:7 AS cpu-builder-amd64 -ARG CMAKE_VERSION -ARG GOLANG_VERSION -COPY ./scripts/rh_linux_deps.sh / -RUN CMAKE_VERSION=${CMAKE_VERSION} GOLANG_VERSION=${GOLANG_VERSION} sh /rh_linux_deps.sh -ENV PATH /opt/rh/devtoolset-10/root/usr/bin:$PATH -COPY --from=llm-code / /go/src/github.com/ollama/ollama/ -ARG OLLAMA_CUSTOM_CPU_DEFS -ARG CGO_CFLAGS -WORKDIR /go/src/github.com/ollama/ollama/llm/generate - -FROM --platform=linux/amd64 cpu-builder-amd64 AS static-build-amd64 -RUN OLLAMA_CPU_TARGET="static" sh gen_linux.sh -FROM --platform=linux/amd64 cpu-builder-amd64 AS cpu-build-amd64 -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_CPU_TARGET="cpu" sh gen_linux.sh -FROM --platform=linux/amd64 cpu-builder-amd64 AS cpu_avx-build-amd64 -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_CPU_TARGET="cpu_avx" sh gen_linux.sh -FROM --platform=linux/amd64 cpu-builder-amd64 AS cpu_avx2-build-amd64 -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_CPU_TARGET="cpu_avx2" sh gen_linux.sh - -FROM --platform=linux/arm64 rockylinux:8 AS cpu-builder-arm64 -ARG CMAKE_VERSION -ARG GOLANG_VERSION -COPY ./scripts/rh_linux_deps.sh / -RUN CMAKE_VERSION=${CMAKE_VERSION} GOLANG_VERSION=${GOLANG_VERSION} sh /rh_linux_deps.sh -ENV PATH /opt/rh/gcc-toolset-10/root/usr/bin:$PATH -COPY --from=llm-code / /go/src/github.com/ollama/ollama/ -ARG OLLAMA_CUSTOM_CPU_DEFS -ARG CGO_CFLAGS -WORKDIR /go/src/github.com/ollama/ollama/llm/generate - -FROM --platform=linux/arm64 cpu-builder-arm64 AS static-build-arm64 -RUN OLLAMA_CPU_TARGET="static" sh gen_linux.sh -FROM --platform=linux/arm64 cpu-builder-arm64 AS cpu-build-arm64 -RUN OLLAMA_SKIP_STATIC_GENERATE=1 OLLAMA_CPU_TARGET="cpu" sh gen_linux.sh - - -# Intermediate stage used for ./scripts/build_linux.sh -FROM --platform=linux/amd64 cpu-build-amd64 AS build-amd64 -ENV CGO_ENABLED 1 -WORKDIR /go/src/github.com/ollama/ollama -COPY . . -COPY --from=static-build-amd64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=cpu_avx-build-amd64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=cpu_avx2-build-amd64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=cuda-build-amd64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=rocm-build-amd64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=rocm-build-amd64 /go/src/github.com/ollama/ollama/dist/deps/ ./dist/deps/ -ARG GOFLAGS -ARG CGO_CFLAGS -RUN go build -trimpath . - -# Intermediate stage used for ./scripts/build_linux.sh -FROM --platform=linux/arm64 cpu-build-arm64 AS build-arm64 -ENV CGO_ENABLED 1 -ARG GOLANG_VERSION -WORKDIR /go/src/github.com/ollama/ollama -COPY . . -COPY --from=static-build-arm64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -COPY --from=cuda-build-arm64 /go/src/github.com/ollama/ollama/llm/build/linux/ llm/build/linux/ -ARG GOFLAGS -ARG CGO_CFLAGS -RUN go build -trimpath . - -# Runtime stages -FROM --platform=linux/amd64 ubuntu:22.04 as runtime-amd64 -RUN apt-get update && apt-get install -y ca-certificates -COPY --from=build-amd64 /go/src/github.com/ollama/ollama/ollama /bin/ollama -FROM --platform=linux/arm64 ubuntu:22.04 as runtime-arm64 -RUN apt-get update && apt-get install -y ca-certificates -COPY --from=build-arm64 /go/src/github.com/ollama/ollama/ollama /bin/ollama - -# Radeon images are much larger so we keep it distinct from the CPU/CUDA image -FROM --platform=linux/amd64 rocm/dev-centos-7:${ROCM_VERSION}-complete as runtime-rocm -RUN update-pciids -COPY --from=build-amd64 /go/src/github.com/ollama/ollama/ollama /bin/ollama -EXPOSE 11434 -ENV OLLAMA_HOST 0.0.0.0 - -ENTRYPOINT ["/bin/ollama"] -CMD ["serve"] - -FROM runtime-$TARGETARCH -EXPOSE 11434 -ENV OLLAMA_HOST 0.0.0.0 -ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -ENV LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64 -ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility -ENV NVIDIA_VISIBLE_DEVICES=all - -ENTRYPOINT ["/bin/ollama"] -CMD ["serve"] diff --git a/ollama/LICENSE b/ollama/LICENSE deleted file mode 100755 index 8e3dc97..0000000 --- a/ollama/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Ollama - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/ollama/README.md b/ollama/README.md deleted file mode 100755 index aae92e6..0000000 --- a/ollama/README.md +++ /dev/null @@ -1,409 +0,0 @@ -
ollama -
- -# Ollama - -[![Discord](https://dcbadge.vercel.app/api/server/ollama?style=flat&compact=true)](https://discord.gg/ollama) - -Get up and running with large language models. - -### macOS - -[Download](https://ollama.com/download/Ollama-darwin.zip) - -### Windows preview - -[Download](https://ollama.com/download/OllamaSetup.exe) - -### Linux - -``` -curl -fsSL https://ollama.com/install.sh | sh -``` - -[Manual install instructions](https://github.com/ollama/ollama/blob/main/docs/linux.md) - -### Docker - -The official [Ollama Docker image](https://hub.docker.com/r/ollama/ollama) `ollama/ollama` is available on Docker Hub. - -### Libraries - -- [ollama-python](https://github.com/ollama/ollama-python) -- [ollama-js](https://github.com/ollama/ollama-js) - -## Quickstart - -To run and chat with [Llama 3.1](https://ollama.com/library/llama3.1): - -``` -ollama run llama3.1 -``` - -## Model library - -Ollama supports a list of models available on [ollama.com/library](https://ollama.com/library 'ollama model library') - -Here are some example models that can be downloaded: - -| Model | Parameters | Size | Download | -| ------------------ | ---------- | ----- | ------------------------------ | -| Llama 3.1 | 8B | 4.7GB | `ollama run llama3.1` | -| Llama 3.1 | 70B | 40GB | `ollama run llama3.1:70b` | -| Llama 3.1 | 405B | 231GB | `ollama run llama3.1:405b` | -| Phi 3 Mini | 3.8B | 2.3GB | `ollama run phi3` | -| Phi 3 Medium | 14B | 7.9GB | `ollama run phi3:medium` | -| Gemma 2 | 2B | 1.6GB | `ollama run gemma2:2b` | -| Gemma 2 | 9B | 5.5GB | `ollama run gemma2` | -| Gemma 2 | 27B | 16GB | `ollama run gemma2:27b` | -| Mistral | 7B | 4.1GB | `ollama run mistral` | -| Moondream 2 | 1.4B | 829MB | `ollama run moondream` | -| Neural Chat | 7B | 4.1GB | `ollama run neural-chat` | -| Starling | 7B | 4.1GB | `ollama run starling-lm` | -| Code Llama | 7B | 3.8GB | `ollama run codellama` | -| Llama 2 Uncensored | 7B | 3.8GB | `ollama run llama2-uncensored` | -| LLaVA | 7B | 4.5GB | `ollama run llava` | -| Solar | 10.7B | 6.1GB | `ollama run solar` | - -> [!NOTE] -> You should have at least 8 GB of RAM available to run the 7B models, 16 GB to run the 13B models, and 32 GB to run the 33B models. - -## Customize a model - -### Import from GGUF - -Ollama supports importing GGUF models in the Modelfile: - -1. Create a file named `Modelfile`, with a `FROM` instruction with the local filepath to the model you want to import. - - ``` - FROM ./vicuna-33b.Q4_0.gguf - ``` - -2. Create the model in Ollama - - ``` - ollama create example -f Modelfile - ``` - -3. Run the model - - ``` - ollama run example - ``` - -### Import from PyTorch or Safetensors - -See the [guide](docs/import.md) on importing models for more information. - -### Customize a prompt - -Models from the Ollama library can be customized with a prompt. For example, to customize the `llama3.1` model: - -``` -ollama pull llama3.1 -``` - -Create a `Modelfile`: - -``` -FROM llama3.1 - -# set the temperature to 1 [higher is more creative, lower is more coherent] -PARAMETER temperature 1 - -# set the system message -SYSTEM """ -You are Mario from Super Mario Bros. Answer as Mario, the assistant, only. -""" -``` - -Next, create and run the model: - -``` -ollama create mario -f ./Modelfile -ollama run mario ->>> hi -Hello! It's your friend Mario. -``` - -For more examples, see the [examples](examples) directory. For more information on working with a Modelfile, see the [Modelfile](docs/modelfile.md) documentation. - -## CLI Reference - -### Create a model - -`ollama create` is used to create a model from a Modelfile. - -``` -ollama create mymodel -f ./Modelfile -``` - -### Pull a model - -``` -ollama pull llama3.1 -``` - -> This command can also be used to update a local model. Only the diff will be pulled. - -### Remove a model - -``` -ollama rm llama3.1 -``` - -### Copy a model - -``` -ollama cp llama3.1 my-model -``` - -### Multiline input - -For multiline input, you can wrap text with `"""`: - -``` ->>> """Hello, -... world! -... """ -I'm a basic program that prints the famous "Hello, world!" message to the console. -``` - -### Multimodal models - -``` -ollama run llava "What's in this image? /Users/jmorgan/Desktop/smile.png" -The image features a yellow smiley face, which is likely the central focus of the picture. -``` - -### Pass the prompt as an argument - -``` -$ ollama run llama3.1 "Summarize this file: $(cat README.md)" - Ollama is a lightweight, extensible framework for building and running language models on the local machine. It provides a simple API for creating, running, and managing models, as well as a library of pre-built models that can be easily used in a variety of applications. -``` - -### Show model information - -``` -ollama show llama3.1 -``` - -### List models on your computer - -``` -ollama list -``` - -### Start Ollama - -`ollama serve` is used when you want to start ollama without running the desktop application. - -## Building - -See the [developer guide](https://github.com/ollama/ollama/blob/main/docs/development.md) - -### Running local builds - -Next, start the server: - -``` -./ollama serve -``` - -Finally, in a separate shell, run a model: - -``` -./ollama run llama3.1 -``` - -## REST API - -Ollama has a REST API for running and managing models. - -### Generate a response - -``` -curl http://localhost:11434/api/generate -d '{ - "model": "llama3.1", - "prompt":"Why is the sky blue?" -}' -``` - -### Chat with a model - -``` -curl http://localhost:11434/api/chat -d '{ - "model": "llama3.1", - "messages": [ - { "role": "user", "content": "why is the sky blue?" } - ] -}' -``` - -See the [API documentation](./docs/api.md) for all endpoints. - -## Community Integrations - -### Web & Desktop - -- [Open WebUI](https://github.com/open-webui/open-webui) -- [Enchanted (macOS native)](https://github.com/AugustDev/enchanted) -- [Hollama](https://github.com/fmaclen/hollama) -- [Lollms-Webui](https://github.com/ParisNeo/lollms-webui) -- [LibreChat](https://github.com/danny-avila/LibreChat) -- [Bionic GPT](https://github.com/bionic-gpt/bionic-gpt) -- [HTML UI](https://github.com/rtcfirefly/ollama-ui) -- [Saddle](https://github.com/jikkuatwork/saddle) -- [Chatbot UI](https://github.com/ivanfioravanti/chatbot-ollama) -- [Chatbot UI v2](https://github.com/mckaywrigley/chatbot-ui) -- [Typescript UI](https://github.com/ollama-interface/Ollama-Gui?tab=readme-ov-file) -- [Minimalistic React UI for Ollama Models](https://github.com/richawo/minimal-llm-ui) -- [Ollamac](https://github.com/kevinhermawan/Ollamac) -- [big-AGI](https://github.com/enricoros/big-AGI/blob/main/docs/config-local-ollama.md) -- [Cheshire Cat assistant framework](https://github.com/cheshire-cat-ai/core) -- [Amica](https://github.com/semperai/amica) -- [chatd](https://github.com/BruceMacD/chatd) -- [Ollama-SwiftUI](https://github.com/kghandour/Ollama-SwiftUI) -- [Dify.AI](https://github.com/langgenius/dify) -- [MindMac](https://mindmac.app) -- [NextJS Web Interface for Ollama](https://github.com/jakobhoeg/nextjs-ollama-llm-ui) -- [Msty](https://msty.app) -- [Chatbox](https://github.com/Bin-Huang/Chatbox) -- [WinForm Ollama Copilot](https://github.com/tgraupmann/WinForm_Ollama_Copilot) -- [NextChat](https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web) with [Get Started Doc](https://docs.nextchat.dev/models/ollama) -- [Alpaca WebUI](https://github.com/mmo80/alpaca-webui) -- [OllamaGUI](https://github.com/enoch1118/ollamaGUI) -- [OpenAOE](https://github.com/InternLM/OpenAOE) -- [Odin Runes](https://github.com/leonid20000/OdinRunes) -- [LLM-X](https://github.com/mrdjohnson/llm-x) (Progressive Web App) -- [AnythingLLM (Docker + MacOs/Windows/Linux native app)](https://github.com/Mintplex-Labs/anything-llm) -- [Ollama Basic Chat: Uses HyperDiv Reactive UI](https://github.com/rapidarchitect/ollama_basic_chat) -- [Ollama-chats RPG](https://github.com/drazdra/ollama-chats) -- [QA-Pilot](https://github.com/reid41/QA-Pilot) (Chat with Code Repository) -- [ChatOllama](https://github.com/sugarforever/chat-ollama) (Open Source Chatbot based on Ollama with Knowledge Bases) -- [CRAG Ollama Chat](https://github.com/Nagi-ovo/CRAG-Ollama-Chat) (Simple Web Search with Corrective RAG) -- [RAGFlow](https://github.com/infiniflow/ragflow) (Open-source Retrieval-Augmented Generation engine based on deep document understanding) -- [StreamDeploy](https://github.com/StreamDeploy-DevRel/streamdeploy-llm-app-scaffold) (LLM Application Scaffold) -- [chat](https://github.com/swuecho/chat) (chat web app for teams) -- [Lobe Chat](https://github.com/lobehub/lobe-chat) with [Integrating Doc](https://lobehub.com/docs/self-hosting/examples/ollama) -- [Ollama RAG Chatbot](https://github.com/datvodinh/rag-chatbot.git) (Local Chat with multiple PDFs using Ollama and RAG) -- [BrainSoup](https://www.nurgo-software.com/products/brainsoup) (Flexible native client with RAG & multi-agent automation) -- [macai](https://github.com/Renset/macai) (macOS client for Ollama, ChatGPT, and other compatible API back-ends) -- [Olpaka](https://github.com/Otacon/olpaka) (User-friendly Flutter Web App for Ollama) -- [OllamaSpring](https://github.com/CrazyNeil/OllamaSpring) (Ollama Client for macOS) -- [LLocal.in](https://github.com/kartikm7/llocal) (Easy to use Electron Desktop Client for Ollama) -- [Ollama with Google Mesop](https://github.com/rapidarchitect/ollama_mesop/) (Mesop Chat Client implementation with Ollama) -- [Kerlig AI](https://www.kerlig.com/) (AI writing assistant for macOS) -- [AI Studio](https://github.com/MindWorkAI/AI-Studio) -- [Sidellama](https://github.com/gyopak/sidellama) (browser-based LLM client) -- [LLMStack](https://github.com/trypromptly/LLMStack) (No-code multi-agent framework to build LLM agents and workflows) -- [BoltAI for Mac](https://boltai.com) (AI Chat Client for Mac) -- [Harbor](https://github.com/av/harbor) (Containerized LLM Toolkit with Ollama as default backend) - -### Terminal - -- [oterm](https://github.com/ggozad/oterm) -- [Ellama Emacs client](https://github.com/s-kostyaev/ellama) -- [Emacs client](https://github.com/zweifisch/ollama) -- [gen.nvim](https://github.com/David-Kunz/gen.nvim) -- [ollama.nvim](https://github.com/nomnivore/ollama.nvim) -- [ollero.nvim](https://github.com/marco-souza/ollero.nvim) -- [ollama-chat.nvim](https://github.com/gerazov/ollama-chat.nvim) -- [ogpt.nvim](https://github.com/huynle/ogpt.nvim) -- [gptel Emacs client](https://github.com/karthink/gptel) -- [Oatmeal](https://github.com/dustinblackman/oatmeal) -- [cmdh](https://github.com/pgibler/cmdh) -- [ooo](https://github.com/npahlfer/ooo) -- [shell-pilot](https://github.com/reid41/shell-pilot) -- [tenere](https://github.com/pythops/tenere) -- [llm-ollama](https://github.com/taketwo/llm-ollama) for [Datasette's LLM CLI](https://llm.datasette.io/en/stable/). -- [typechat-cli](https://github.com/anaisbetts/typechat-cli) -- [ShellOracle](https://github.com/djcopley/ShellOracle) -- [tlm](https://github.com/yusufcanb/tlm) -- [podman-ollama](https://github.com/ericcurtin/podman-ollama) -- [gollama](https://github.com/sammcj/gollama) -- [Ollama eBook Summary](https://github.com/cognitivetech/ollama-ebook-summary/) - -### Database - -- [MindsDB](https://github.com/mindsdb/mindsdb/blob/staging/mindsdb/integrations/handlers/ollama_handler/README.md) (Connects Ollama models with nearly 200 data platforms and apps) -- [chromem-go](https://github.com/philippgille/chromem-go/blob/v0.5.0/embed_ollama.go) with [example](https://github.com/philippgille/chromem-go/tree/v0.5.0/examples/rag-wikipedia-ollama) - -### Package managers - -- [Pacman](https://archlinux.org/packages/extra/x86_64/ollama/) -- [Helm Chart](https://artifacthub.io/packages/helm/ollama-helm/ollama) -- [Guix channel](https://codeberg.org/tusharhero/ollama-guix) - -### Libraries - -- [LangChain](https://python.langchain.com/docs/integrations/llms/ollama) and [LangChain.js](https://js.langchain.com/docs/modules/model_io/models/llms/integrations/ollama) with [example](https://js.langchain.com/docs/use_cases/question_answering/local_retrieval_qa) -- [Firebase Genkit](https://firebase.google.com/docs/genkit/plugins/ollama) -- [LangChainGo](https://github.com/tmc/langchaingo/) with [example](https://github.com/tmc/langchaingo/tree/main/examples/ollama-completion-example) -- [LangChain4j](https://github.com/langchain4j/langchain4j) with [example](https://github.com/langchain4j/langchain4j-examples/tree/main/ollama-examples/src/main/java) -- [LangChainRust](https://github.com/Abraxas-365/langchain-rust) with [example](https://github.com/Abraxas-365/langchain-rust/blob/main/examples/llm_ollama.rs) -- [LlamaIndex](https://gpt-index.readthedocs.io/en/stable/examples/llm/ollama.html) -- [LiteLLM](https://github.com/BerriAI/litellm) -- [OllamaSharp for .NET](https://github.com/awaescher/OllamaSharp) -- [Ollama for Ruby](https://github.com/gbaptista/ollama-ai) -- [Ollama-rs for Rust](https://github.com/pepperoni21/ollama-rs) -- [Ollama-hpp for C++](https://github.com/jmont-dev/ollama-hpp) -- [Ollama4j for Java](https://github.com/amithkoujalgi/ollama4j) -- [ModelFusion Typescript Library](https://modelfusion.dev/integration/model-provider/ollama) -- [OllamaKit for Swift](https://github.com/kevinhermawan/OllamaKit) -- [Ollama for Dart](https://github.com/breitburg/dart-ollama) -- [Ollama for Laravel](https://github.com/cloudstudio/ollama-laravel) -- [LangChainDart](https://github.com/davidmigloz/langchain_dart) -- [Semantic Kernel - Python](https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/ai/ollama) -- [Haystack](https://github.com/deepset-ai/haystack-integrations/blob/main/integrations/ollama.md) -- [Elixir LangChain](https://github.com/brainlid/langchain) -- [Ollama for R - rollama](https://github.com/JBGruber/rollama) -- [Ollama for R - ollama-r](https://github.com/hauselin/ollama-r) -- [Ollama-ex for Elixir](https://github.com/lebrunel/ollama-ex) -- [Ollama Connector for SAP ABAP](https://github.com/b-tocs/abap_btocs_ollama) -- [Testcontainers](https://testcontainers.com/modules/ollama/) -- [Portkey](https://portkey.ai/docs/welcome/integration-guides/ollama) -- [PromptingTools.jl](https://github.com/svilupp/PromptingTools.jl) with an [example](https://svilupp.github.io/PromptingTools.jl/dev/examples/working_with_ollama) -- [LlamaScript](https://github.com/Project-Llama/llamascript) - -### Mobile - -- [Enchanted](https://github.com/AugustDev/enchanted) -- [Maid](https://github.com/Mobile-Artificial-Intelligence/maid) - -### Extensions & Plugins - -- [Raycast extension](https://github.com/MassimilianoPasquini97/raycast_ollama) -- [Discollama](https://github.com/mxyng/discollama) (Discord bot inside the Ollama discord channel) -- [Continue](https://github.com/continuedev/continue) -- [Obsidian Ollama plugin](https://github.com/hinterdupfinger/obsidian-ollama) -- [Logseq Ollama plugin](https://github.com/omagdy7/ollama-logseq) -- [NotesOllama](https://github.com/andersrex/notesollama) (Apple Notes Ollama plugin) -- [Dagger Chatbot](https://github.com/samalba/dagger-chatbot) -- [Discord AI Bot](https://github.com/mekb-turtle/discord-ai-bot) -- [Ollama Telegram Bot](https://github.com/ruecat/ollama-telegram) -- [Hass Ollama Conversation](https://github.com/ej52/hass-ollama-conversation) -- [Rivet plugin](https://github.com/abrenneke/rivet-plugin-ollama) -- [Obsidian BMO Chatbot plugin](https://github.com/longy2k/obsidian-bmo-chatbot) -- [Cliobot](https://github.com/herval/cliobot) (Telegram bot with Ollama support) -- [Copilot for Obsidian plugin](https://github.com/logancyang/obsidian-copilot) -- [Obsidian Local GPT plugin](https://github.com/pfrankov/obsidian-local-gpt) -- [Open Interpreter](https://docs.openinterpreter.com/language-model-setup/local-models/ollama) -- [Llama Coder](https://github.com/ex3ndr/llama-coder) (Copilot alternative using Ollama) -- [Ollama Copilot](https://github.com/bernardo-bruning/ollama-copilot) (Proxy that allows you to use ollama as a copilot like Github copilot) -- [twinny](https://github.com/rjmacarthy/twinny) (Copilot and Copilot chat alternative using Ollama) -- [Wingman-AI](https://github.com/RussellCanfield/wingman-ai) (Copilot code and chat alternative using Ollama and Hugging Face) -- [Page Assist](https://github.com/n4ze3m/page-assist) (Chrome Extension) -- [AI Telegram Bot](https://github.com/tusharhero/aitelegrambot) (Telegram bot using Ollama in backend) -- [AI ST Completion](https://github.com/yaroslavyaroslav/OpenAI-sublime-text) (Sublime Text 4 AI assistant plugin with Ollama support) -- [Discord-Ollama Chat Bot](https://github.com/kevinthedang/discord-ollama) (Generalized TypeScript Discord Bot w/ Tuning Documentation) -- [Discord AI chat/moderation bot](https://github.com/rapmd73/Companion) Chat/moderation bot written in python. Uses Ollama to create personalities. -- [Headless Ollama](https://github.com/nischalj10/headless-ollama) (Scripts to automatically install ollama client & models on any OS for apps that depends on ollama server) - -### Supported backends - -- [llama.cpp](https://github.com/ggerganov/llama.cpp) project founded by Georgi Gerganov. - diff --git a/ollama/SECURITY.md b/ollama/SECURITY.md deleted file mode 100755 index d38bb7c..0000000 --- a/ollama/SECURITY.md +++ /dev/null @@ -1,25 +0,0 @@ -# Security - -The Ollama maintainer team takes security seriously and will actively work to resolve security issues. - -## Reporting a vulnerability - -If you discover a security vulnerability, please do not open a public issue. Instead, please report it by emailing hello@ollama.com. We ask that you give us sufficient time to investigate and address the vulnerability before disclosing it publicly. - -Please include the following details in your report: -- A description of the vulnerability -- Steps to reproduce the issue -- Your assessment of the potential impact -- Any possible mitigations - -## Security best practices - -While the maintainer team does their best to secure Ollama, users are encouraged to implement their own security best practices, such as: - -- Regularly updating to the latest version of Ollama -- Securing access to hosted instances of Ollama -- Monitoring systems for unusual activity - -## Contact - -For any other questions or concerns related to security, please contact us at hello@ollama.com diff --git a/ollama/api/client.go b/ollama/api/client.go deleted file mode 100755 index bbdf820..0000000 --- a/ollama/api/client.go +++ /dev/null @@ -1,380 +0,0 @@ -// Package api implements the client-side API for code wishing to interact -// with the ollama service. The methods of the [Client] type correspond to -// the ollama REST API as described in [the API documentation]. -// The ollama command-line client itself uses this package to interact with -// the backend service. -// -// # Examples -// -// Several examples of using this package are available [in the GitHub -// repository]. -// -// [the API documentation]: https://github.com/ollama/ollama/blob/main/docs/api.md -// [in the GitHub repository]: https://github.com/ollama/ollama/tree/main/examples -package api - -import ( - "bufio" - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "runtime" - - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/format" - "github.com/ollama/ollama/version" -) - -// Client encapsulates client state for interacting with the ollama -// service. Use [ClientFromEnvironment] to create new Clients. -type Client struct { - base *url.URL - http *http.Client -} - -func checkError(resp *http.Response, body []byte) error { - if resp.StatusCode < http.StatusBadRequest { - return nil - } - - apiError := StatusError{StatusCode: resp.StatusCode} - - err := json.Unmarshal(body, &apiError) - if err != nil { - // Use the full body as the message if we fail to decode a response. - apiError.ErrorMessage = string(body) - } - - return apiError -} - -// ClientFromEnvironment creates a new [Client] using configuration from the -// environment variable OLLAMA_HOST, which points to the network host and -// port on which the ollama service is listenting. The format of this variable -// is: -// -// ://: -// -// If the variable is not specified, a default ollama host and port will be -// used. -func ClientFromEnvironment() (*Client, error) { - return &Client{ - base: envconfig.Host(), - http: http.DefaultClient, - }, nil -} - -func NewClient(base *url.URL, http *http.Client) *Client { - return &Client{ - base: base, - http: http, - } -} - -func (c *Client) do(ctx context.Context, method, path string, reqData, respData any) error { - var reqBody io.Reader - var data []byte - var err error - - switch reqData := reqData.(type) { - case io.Reader: - // reqData is already an io.Reader - reqBody = reqData - case nil: - // noop - default: - data, err = json.Marshal(reqData) - if err != nil { - return err - } - - reqBody = bytes.NewReader(data) - } - - requestURL := c.base.JoinPath(path) - request, err := http.NewRequestWithContext(ctx, method, requestURL.String(), reqBody) - if err != nil { - return err - } - - request.Header.Set("Content-Type", "application/json") - request.Header.Set("Accept", "application/json") - request.Header.Set("User-Agent", fmt.Sprintf("ollama/%s (%s %s) Go/%s", version.Version, runtime.GOARCH, runtime.GOOS, runtime.Version())) - - respObj, err := c.http.Do(request) - if err != nil { - return err - } - defer respObj.Body.Close() - - respBody, err := io.ReadAll(respObj.Body) - if err != nil { - return err - } - - if err := checkError(respObj, respBody); err != nil { - return err - } - - if len(respBody) > 0 && respData != nil { - if err := json.Unmarshal(respBody, respData); err != nil { - return err - } - } - return nil -} - -const maxBufferSize = 512 * format.KiloByte - -func (c *Client) stream(ctx context.Context, method, path string, data any, fn func([]byte) error) error { - var buf *bytes.Buffer - if data != nil { - bts, err := json.Marshal(data) - if err != nil { - return err - } - - buf = bytes.NewBuffer(bts) - } - - requestURL := c.base.JoinPath(path) - request, err := http.NewRequestWithContext(ctx, method, requestURL.String(), buf) - if err != nil { - return err - } - - request.Header.Set("Content-Type", "application/json") - request.Header.Set("Accept", "application/x-ndjson") - request.Header.Set("User-Agent", fmt.Sprintf("ollama/%s (%s %s) Go/%s", version.Version, runtime.GOARCH, runtime.GOOS, runtime.Version())) - - response, err := c.http.Do(request) - if err != nil { - return err - } - defer response.Body.Close() - - scanner := bufio.NewScanner(response.Body) - // increase the buffer size to avoid running out of space - scanBuf := make([]byte, 0, maxBufferSize) - scanner.Buffer(scanBuf, maxBufferSize) - for scanner.Scan() { - var errorResponse struct { - Error string `json:"error,omitempty"` - } - - bts := scanner.Bytes() - if err := json.Unmarshal(bts, &errorResponse); err != nil { - return fmt.Errorf("unmarshal: %w", err) - } - - if errorResponse.Error != "" { - return errors.New(errorResponse.Error) - } - - if response.StatusCode >= http.StatusBadRequest { - return StatusError{ - StatusCode: response.StatusCode, - Status: response.Status, - ErrorMessage: errorResponse.Error, - } - } - - if err := fn(bts); err != nil { - return err - } - } - - return nil -} - -// GenerateResponseFunc is a function that [Client.Generate] invokes every time -// a response is received from the service. If this function returns an error, -// [Client.Generate] will stop generating and return this error. -type GenerateResponseFunc func(GenerateResponse) error - -// Generate generates a response for a given prompt. The req parameter should -// be populated with prompt details. fn is called for each response (there may -// be multiple responses, e.g. in case streaming is enabled). -func (c *Client) Generate(ctx context.Context, req *GenerateRequest, fn GenerateResponseFunc) error { - return c.stream(ctx, http.MethodPost, "/api/generate", req, func(bts []byte) error { - var resp GenerateResponse - if err := json.Unmarshal(bts, &resp); err != nil { - return err - } - - return fn(resp) - }) -} - -// ChatResponseFunc is a function that [Client.Chat] invokes every time -// a response is received from the service. If this function returns an error, -// [Client.Chat] will stop generating and return this error. -type ChatResponseFunc func(ChatResponse) error - -// Chat generates the next message in a chat. [ChatRequest] may contain a -// sequence of messages which can be used to maintain chat history with a model. -// fn is called for each response (there may be multiple responses, e.g. if case -// streaming is enabled). -func (c *Client) Chat(ctx context.Context, req *ChatRequest, fn ChatResponseFunc) error { - return c.stream(ctx, http.MethodPost, "/api/chat", req, func(bts []byte) error { - var resp ChatResponse - if err := json.Unmarshal(bts, &resp); err != nil { - return err - } - - return fn(resp) - }) -} - -// PullProgressFunc is a function that [Client.Pull] invokes every time there -// is progress with a "pull" request sent to the service. If this function -// returns an error, [Client.Pull] will stop the process and return this error. -type PullProgressFunc func(ProgressResponse) error - -// Pull downloads a model from the ollama library. fn is called each time -// progress is made on the request and can be used to display a progress bar, -// etc. -func (c *Client) Pull(ctx context.Context, req *PullRequest, fn PullProgressFunc) error { - return c.stream(ctx, http.MethodPost, "/api/pull", req, func(bts []byte) error { - var resp ProgressResponse - if err := json.Unmarshal(bts, &resp); err != nil { - return err - } - - return fn(resp) - }) -} - -// PushProgressFunc is a function that [Client.Push] invokes when progress is -// made. -// It's similar to other progress function types like [PullProgressFunc]. -type PushProgressFunc func(ProgressResponse) error - -// Push uploads a model to the model library; requires registering for ollama.ai -// and adding a public key first. fn is called each time progress is made on -// the request and can be used to display a progress bar, etc. -func (c *Client) Push(ctx context.Context, req *PushRequest, fn PushProgressFunc) error { - return c.stream(ctx, http.MethodPost, "/api/push", req, func(bts []byte) error { - var resp ProgressResponse - if err := json.Unmarshal(bts, &resp); err != nil { - return err - } - - return fn(resp) - }) -} - -// CreateProgressFunc is a function that [Client.Create] invokes when progress -// is made. -// It's similar to other progress function types like [PullProgressFunc]. -type CreateProgressFunc func(ProgressResponse) error - -// Create creates a model from a [Modelfile]. fn is a progress function that -// behaves similarly to other methods (see [Client.Pull]). -// -// [Modelfile]: https://github.com/ollama/ollama/blob/main/docs/modelfile.md -func (c *Client) Create(ctx context.Context, req *CreateRequest, fn CreateProgressFunc) error { - return c.stream(ctx, http.MethodPost, "/api/create", req, func(bts []byte) error { - var resp ProgressResponse - if err := json.Unmarshal(bts, &resp); err != nil { - return err - } - - return fn(resp) - }) -} - -// List lists models that are available locally. -func (c *Client) List(ctx context.Context) (*ListResponse, error) { - var lr ListResponse - if err := c.do(ctx, http.MethodGet, "/api/tags", nil, &lr); err != nil { - return nil, err - } - return &lr, nil -} - -// List running models. -func (c *Client) ListRunning(ctx context.Context) (*ProcessResponse, error) { - var lr ProcessResponse - if err := c.do(ctx, http.MethodGet, "/api/ps", nil, &lr); err != nil { - return nil, err - } - return &lr, nil -} - -// Copy copies a model - creating a model with another name from an existing -// model. -func (c *Client) Copy(ctx context.Context, req *CopyRequest) error { - if err := c.do(ctx, http.MethodPost, "/api/copy", req, nil); err != nil { - return err - } - return nil -} - -// Delete deletes a model and its data. -func (c *Client) Delete(ctx context.Context, req *DeleteRequest) error { - if err := c.do(ctx, http.MethodDelete, "/api/delete", req, nil); err != nil { - return err - } - return nil -} - -// Show obtains model information, including details, modelfile, license etc. -func (c *Client) Show(ctx context.Context, req *ShowRequest) (*ShowResponse, error) { - var resp ShowResponse - if err := c.do(ctx, http.MethodPost, "/api/show", req, &resp); err != nil { - return nil, err - } - return &resp, nil -} - -// Hearbeat checks if the server has started and is responsive; if yes, it -// returns nil, otherwise an error. -func (c *Client) Heartbeat(ctx context.Context) error { - if err := c.do(ctx, http.MethodHead, "/", nil, nil); err != nil { - return err - } - return nil -} - -// Embed generates embeddings from a model. -func (c *Client) Embed(ctx context.Context, req *EmbedRequest) (*EmbedResponse, error) { - var resp EmbedResponse - if err := c.do(ctx, http.MethodPost, "/api/embed", req, &resp); err != nil { - return nil, err - } - return &resp, nil -} - -// Embeddings generates an embedding from a model. -func (c *Client) Embeddings(ctx context.Context, req *EmbeddingRequest) (*EmbeddingResponse, error) { - var resp EmbeddingResponse - if err := c.do(ctx, http.MethodPost, "/api/embeddings", req, &resp); err != nil { - return nil, err - } - return &resp, nil -} - -// CreateBlob creates a blob from a file on the server. digest is the -// expected SHA256 digest of the file, and r represents the file. -func (c *Client) CreateBlob(ctx context.Context, digest string, r io.Reader) error { - return c.do(ctx, http.MethodPost, fmt.Sprintf("/api/blobs/%s", digest), r, nil) -} - -// Version returns the Ollama server version as a string. -func (c *Client) Version(ctx context.Context) (string, error) { - var version struct { - Version string `json:"version"` - } - - if err := c.do(ctx, http.MethodGet, "/api/version", nil, &version); err != nil { - return "", err - } - - return version.Version, nil -} diff --git a/ollama/api/client_test.go b/ollama/api/client_test.go deleted file mode 100755 index 23fe933..0000000 --- a/ollama/api/client_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package api - -import ( - "testing" -) - -func TestClientFromEnvironment(t *testing.T) { - type testCase struct { - value string - expect string - err error - } - - testCases := map[string]*testCase{ - "empty": {value: "", expect: "http://127.0.0.1:11434"}, - "only address": {value: "1.2.3.4", expect: "http://1.2.3.4:11434"}, - "only port": {value: ":1234", expect: "http://:1234"}, - "address and port": {value: "1.2.3.4:1234", expect: "http://1.2.3.4:1234"}, - "scheme http and address": {value: "http://1.2.3.4", expect: "http://1.2.3.4:80"}, - "scheme https and address": {value: "https://1.2.3.4", expect: "https://1.2.3.4:443"}, - "scheme, address, and port": {value: "https://1.2.3.4:1234", expect: "https://1.2.3.4:1234"}, - "hostname": {value: "example.com", expect: "http://example.com:11434"}, - "hostname and port": {value: "example.com:1234", expect: "http://example.com:1234"}, - "scheme http and hostname": {value: "http://example.com", expect: "http://example.com:80"}, - "scheme https and hostname": {value: "https://example.com", expect: "https://example.com:443"}, - "scheme, hostname, and port": {value: "https://example.com:1234", expect: "https://example.com:1234"}, - "trailing slash": {value: "example.com/", expect: "http://example.com:11434"}, - "trailing slash port": {value: "example.com:1234/", expect: "http://example.com:1234"}, - } - - for k, v := range testCases { - t.Run(k, func(t *testing.T) { - t.Setenv("OLLAMA_HOST", v.value) - - client, err := ClientFromEnvironment() - if err != v.err { - t.Fatalf("expected %s, got %s", v.err, err) - } - - if client.base.String() != v.expect { - t.Fatalf("expected %s, got %s", v.expect, client.base.String()) - } - }) - } -} diff --git a/ollama/api/types.go b/ollama/api/types.go deleted file mode 100755 index 2f5a942..0000000 --- a/ollama/api/types.go +++ /dev/null @@ -1,731 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "log/slog" - "math" - "os" - "reflect" - "strconv" - "strings" - "time" -) - -// StatusError is an error with and HTTP status code. -type StatusError struct { - StatusCode int - Status string - ErrorMessage string `json:"error"` -} - -func (e StatusError) Error() string { - switch { - case e.Status != "" && e.ErrorMessage != "": - return fmt.Sprintf("%s: %s", e.Status, e.ErrorMessage) - case e.Status != "": - return e.Status - case e.ErrorMessage != "": - return e.ErrorMessage - default: - // this should not happen - return "something went wrong, please see the ollama server logs for details" - } -} - -// ImageData represents the raw binary data of an image file. -type ImageData []byte - -// GenerateRequest describes a request sent by [Client.Generate]. While you -// have to specify the Model and Prompt fields, all the other fields have -// reasonable defaults for basic uses. -type GenerateRequest struct { - // Model is the model name; it should be a name familiar to Ollama from - // the library at https://ollama.com/library - Model string `json:"model"` - - // Prompt is the textual prompt to send to the model. - Prompt string `json:"prompt"` - - // Suffix is the text that comes after the inserted text. - Suffix string `json:"suffix"` - - // System overrides the model's default system message/prompt. - System string `json:"system"` - - // Template overrides the model's default prompt template. - Template string `json:"template"` - - // Context is the context parameter returned from a previous call to - // Generate call. It can be used to keep a short conversational memory. - Context []int `json:"context,omitempty"` - - // Stream specifies whether the response is streaming; it is true by default. - Stream *bool `json:"stream,omitempty"` - - // Raw set to true means that no formatting will be applied to the prompt. - Raw bool `json:"raw,omitempty"` - - // Format specifies the format to return a response in. - Format string `json:"format"` - - // KeepAlive controls how long the model will stay loaded in memory following - // this request. - KeepAlive *Duration `json:"keep_alive,omitempty"` - - // Images is an optional list of base64-encoded images accompanying this - // request, for multimodal models. - Images []ImageData `json:"images,omitempty"` - - // Options lists model-specific options. For example, temperature can be - // set through this field, if the model supports it. - Options map[string]interface{} `json:"options"` -} - -// ChatRequest describes a request sent by [Client.Chat]. -type ChatRequest struct { - // Model is the model name, as in [GenerateRequest]. - Model string `json:"model"` - - // Messages is the messages of the chat - can be used to keep a chat memory. - Messages []Message `json:"messages"` - - // Stream enable streaming of returned response; true by default. - Stream *bool `json:"stream,omitempty"` - - // Format is the format to return the response in (e.g. "json"). - Format string `json:"format"` - - // KeepAlive controls how long the model will stay loaded into memory - // followin the request. - KeepAlive *Duration `json:"keep_alive,omitempty"` - - // Tools is an optional list of tools the model has access to. - Tools `json:"tools,omitempty"` - - // Options lists model-specific options. - Options map[string]interface{} `json:"options"` -} - -type Tools []Tool - -func (t Tools) String() string { - bts, _ := json.Marshal(t) - return string(bts) -} - -func (t Tool) String() string { - bts, _ := json.Marshal(t) - return string(bts) -} - -// Message is a single message in a chat sequence. The message contains the -// role ("system", "user", or "assistant"), the content and an optional list -// of images. -type Message struct { - Role string `json:"role"` - Content string `json:"content"` - Images []ImageData `json:"images,omitempty"` - ToolCalls []ToolCall `json:"tool_calls,omitempty"` -} - -func (m *Message) UnmarshalJSON(b []byte) error { - type Alias Message - var a Alias - if err := json.Unmarshal(b, &a); err != nil { - return err - } - - *m = Message(a) - m.Role = strings.ToLower(m.Role) - return nil -} - -type ToolCall struct { - Function ToolCallFunction `json:"function"` -} - -type ToolCallFunction struct { - Name string `json:"name"` - Arguments ToolCallFunctionArguments `json:"arguments"` -} - -type ToolCallFunctionArguments map[string]any - -func (t *ToolCallFunctionArguments) String() string { - bts, _ := json.Marshal(t) - return string(bts) -} - -type Tool struct { - Type string `json:"type"` - Function ToolFunction `json:"function"` -} - -type ToolFunction struct { - Name string `json:"name"` - Description string `json:"description"` - Parameters struct { - Type string `json:"type"` - Required []string `json:"required"` - Properties map[string]struct { - Type string `json:"type"` - Description string `json:"description"` - Enum []string `json:"enum,omitempty"` - } `json:"properties"` - } `json:"parameters"` -} - -func (t *ToolFunction) String() string { - bts, _ := json.Marshal(t) - return string(bts) -} - -// ChatResponse is the response returned by [Client.Chat]. Its fields are -// similar to [GenerateResponse]. -type ChatResponse struct { - Model string `json:"model"` - CreatedAt time.Time `json:"created_at"` - Message Message `json:"message"` - DoneReason string `json:"done_reason,omitempty"` - - Done bool `json:"done"` - - Metrics -} - -type Metrics struct { - TotalDuration time.Duration `json:"total_duration,omitempty"` - LoadDuration time.Duration `json:"load_duration,omitempty"` - PromptEvalCount int `json:"prompt_eval_count,omitempty"` - PromptEvalDuration time.Duration `json:"prompt_eval_duration,omitempty"` - EvalCount int `json:"eval_count,omitempty"` - EvalDuration time.Duration `json:"eval_duration,omitempty"` -} - -// Options specified in [GenerateRequest], if you add a new option here add it -// to the API docs also. -type Options struct { - Runner - - // Predict options used at runtime - NumKeep int `json:"num_keep,omitempty"` - Seed int `json:"seed,omitempty"` - NumPredict int `json:"num_predict,omitempty"` - TopK int `json:"top_k,omitempty"` - TopP float32 `json:"top_p,omitempty"` - MinP float32 `json:"min_p,omitempty"` - TFSZ float32 `json:"tfs_z,omitempty"` - TypicalP float32 `json:"typical_p,omitempty"` - RepeatLastN int `json:"repeat_last_n,omitempty"` - Temperature float32 `json:"temperature,omitempty"` - RepeatPenalty float32 `json:"repeat_penalty,omitempty"` - PresencePenalty float32 `json:"presence_penalty,omitempty"` - FrequencyPenalty float32 `json:"frequency_penalty,omitempty"` - Mirostat int `json:"mirostat,omitempty"` - MirostatTau float32 `json:"mirostat_tau,omitempty"` - MirostatEta float32 `json:"mirostat_eta,omitempty"` - PenalizeNewline bool `json:"penalize_newline,omitempty"` - Stop []string `json:"stop,omitempty"` -} - -// Runner options which must be set when the model is loaded into memory -type Runner struct { - NumCtx int `json:"num_ctx,omitempty"` - NumBatch int `json:"num_batch,omitempty"` - NumGPU int `json:"num_gpu,omitempty"` - MainGPU int `json:"main_gpu,omitempty"` - LowVRAM bool `json:"low_vram,omitempty"` - F16KV bool `json:"f16_kv,omitempty"` - LogitsAll bool `json:"logits_all,omitempty"` - VocabOnly bool `json:"vocab_only,omitempty"` - UseMMap *bool `json:"use_mmap,omitempty"` - UseMLock bool `json:"use_mlock,omitempty"` - NumThread int `json:"num_thread,omitempty"` -} - -// EmbedRequest is the request passed to [Client.Embed]. -type EmbedRequest struct { - // Model is the model name. - Model string `json:"model"` - - // Input is the input to embed. - Input any `json:"input"` - - // KeepAlive controls how long the model will stay loaded in memory following - // this request. - KeepAlive *Duration `json:"keep_alive,omitempty"` - - Truncate *bool `json:"truncate,omitempty"` - - // Options lists model-specific options. - Options map[string]interface{} `json:"options"` -} - -// EmbedResponse is the response from [Client.Embed]. -type EmbedResponse struct { - Model string `json:"model"` - Embeddings [][]float32 `json:"embeddings"` - - TotalDuration time.Duration `json:"total_duration,omitempty"` - LoadDuration time.Duration `json:"load_duration,omitempty"` - PromptEvalCount int `json:"prompt_eval_count,omitempty"` -} - -// EmbeddingRequest is the request passed to [Client.Embeddings]. -type EmbeddingRequest struct { - // Model is the model name. - Model string `json:"model"` - - // Prompt is the textual prompt to embed. - Prompt string `json:"prompt"` - - // KeepAlive controls how long the model will stay loaded in memory following - // this request. - KeepAlive *Duration `json:"keep_alive,omitempty"` - - // Options lists model-specific options. - Options map[string]interface{} `json:"options"` -} - -// EmbeddingResponse is the response from [Client.Embeddings]. -type EmbeddingResponse struct { - Embedding []float64 `json:"embedding"` -} - -// CreateRequest is the request passed to [Client.Create]. -type CreateRequest struct { - Model string `json:"model"` - Path string `json:"path"` - Modelfile string `json:"modelfile"` - Stream *bool `json:"stream,omitempty"` - Quantize string `json:"quantize,omitempty"` - - // Name is deprecated, see Model - Name string `json:"name"` - - // Quantization is deprecated, see Quantize - Quantization string `json:"quantization,omitempty"` -} - -// DeleteRequest is the request passed to [Client.Delete]. -type DeleteRequest struct { - Model string `json:"model"` - - // Name is deprecated, see Model - Name string `json:"name"` -} - -// ShowRequest is the request passed to [Client.Show]. -type ShowRequest struct { - Model string `json:"model"` - System string `json:"system"` - - // Template is deprecated - Template string `json:"template"` - Verbose bool `json:"verbose"` - - Options map[string]interface{} `json:"options"` - - // Name is deprecated, see Model - Name string `json:"name"` -} - -// ShowResponse is the response returned from [Client.Show]. -type ShowResponse struct { - License string `json:"license,omitempty"` - Modelfile string `json:"modelfile,omitempty"` - Parameters string `json:"parameters,omitempty"` - Template string `json:"template,omitempty"` - System string `json:"system,omitempty"` - Details ModelDetails `json:"details,omitempty"` - Messages []Message `json:"messages,omitempty"` - ModelInfo map[string]any `json:"model_info,omitempty"` - ProjectorInfo map[string]any `json:"projector_info,omitempty"` - ModifiedAt time.Time `json:"modified_at,omitempty"` -} - -// CopyRequest is the request passed to [Client.Copy]. -type CopyRequest struct { - Source string `json:"source"` - Destination string `json:"destination"` -} - -// PullRequest is the request passed to [Client.Pull]. -type PullRequest struct { - Model string `json:"model"` - Insecure bool `json:"insecure,omitempty"` - Username string `json:"username"` - Password string `json:"password"` - Stream *bool `json:"stream,omitempty"` - - // Name is deprecated, see Model - Name string `json:"name"` -} - -// ProgressResponse is the response passed to progress functions like -// [PullProgressFunc] and [PushProgressFunc]. -type ProgressResponse struct { - Status string `json:"status"` - Digest string `json:"digest,omitempty"` - Total int64 `json:"total,omitempty"` - Completed int64 `json:"completed,omitempty"` -} - -// PushRequest is the request passed to [Client.Push]. -type PushRequest struct { - Model string `json:"model"` - Insecure bool `json:"insecure,omitempty"` - Username string `json:"username"` - Password string `json:"password"` - Stream *bool `json:"stream,omitempty"` - - // Name is deprecated, see Model - Name string `json:"name"` -} - -// ListResponse is the response from [Client.List]. -type ListResponse struct { - Models []ListModelResponse `json:"models"` -} - -// ProcessResponse is the response from [Client.Process]. -type ProcessResponse struct { - Models []ProcessModelResponse `json:"models"` -} - -// ListModelResponse is a single model description in [ListResponse]. -type ListModelResponse struct { - Name string `json:"name"` - Model string `json:"model"` - ModifiedAt time.Time `json:"modified_at"` - Size int64 `json:"size"` - Digest string `json:"digest"` - Details ModelDetails `json:"details,omitempty"` -} - -// ProcessModelResponse is a single model description in [ProcessResponse]. -type ProcessModelResponse struct { - Name string `json:"name"` - Model string `json:"model"` - Size int64 `json:"size"` - Digest string `json:"digest"` - Details ModelDetails `json:"details,omitempty"` - ExpiresAt time.Time `json:"expires_at"` - SizeVRAM int64 `json:"size_vram"` -} - -type RetrieveModelResponse struct { - Id string `json:"id"` - Object string `json:"object"` - Created int64 `json:"created"` - OwnedBy string `json:"owned_by"` -} - -type TokenResponse struct { - Token string `json:"token"` -} - -// GenerateResponse is the response passed into [GenerateResponseFunc]. -type GenerateResponse struct { - // Model is the model name that generated the response. - Model string `json:"model"` - - // CreatedAt is the timestamp of the response. - CreatedAt time.Time `json:"created_at"` - - // Response is the textual response itself. - Response string `json:"response"` - - // Done specifies if the response is complete. - Done bool `json:"done"` - - // DoneReason is the reason the model stopped generating text. - DoneReason string `json:"done_reason,omitempty"` - - // Context is an encoding of the conversation used in this response; this - // can be sent in the next request to keep a conversational memory. - Context []int `json:"context,omitempty"` - - Metrics -} - -// ModelDetails provides details about a model. -type ModelDetails struct { - ParentModel string `json:"parent_model"` - Format string `json:"format"` - Family string `json:"family"` - Families []string `json:"families"` - ParameterSize string `json:"parameter_size"` - QuantizationLevel string `json:"quantization_level"` -} - -func (m *Metrics) Summary() { - if m.TotalDuration > 0 { - fmt.Fprintf(os.Stderr, "total duration: %v\n", m.TotalDuration) - } - - if m.LoadDuration > 0 { - fmt.Fprintf(os.Stderr, "load duration: %v\n", m.LoadDuration) - } - - if m.PromptEvalCount > 0 { - fmt.Fprintf(os.Stderr, "prompt eval count: %d token(s)\n", m.PromptEvalCount) - } - - if m.PromptEvalDuration > 0 { - fmt.Fprintf(os.Stderr, "prompt eval duration: %s\n", m.PromptEvalDuration) - fmt.Fprintf(os.Stderr, "prompt eval rate: %.2f tokens/s\n", float64(m.PromptEvalCount)/m.PromptEvalDuration.Seconds()) - } - - if m.EvalCount > 0 { - fmt.Fprintf(os.Stderr, "eval count: %d token(s)\n", m.EvalCount) - } - - if m.EvalDuration > 0 { - fmt.Fprintf(os.Stderr, "eval duration: %s\n", m.EvalDuration) - fmt.Fprintf(os.Stderr, "eval rate: %.2f tokens/s\n", float64(m.EvalCount)/m.EvalDuration.Seconds()) - } -} - -func (opts *Options) FromMap(m map[string]interface{}) error { - valueOpts := reflect.ValueOf(opts).Elem() // names of the fields in the options struct - typeOpts := reflect.TypeOf(opts).Elem() // types of the fields in the options struct - - // build map of json struct tags to their types - jsonOpts := make(map[string]reflect.StructField) - for _, field := range reflect.VisibleFields(typeOpts) { - jsonTag := strings.Split(field.Tag.Get("json"), ",")[0] - if jsonTag != "" { - jsonOpts[jsonTag] = field - } - } - - for key, val := range m { - opt, ok := jsonOpts[key] - if !ok { - slog.Warn("invalid option provided", "option", key) - continue - } - - field := valueOpts.FieldByName(opt.Name) - if field.IsValid() && field.CanSet() { - if val == nil { - continue - } - - switch field.Kind() { - case reflect.Int: - switch t := val.(type) { - case int64: - field.SetInt(t) - case float64: - // when JSON unmarshals numbers, it uses float64, not int - field.SetInt(int64(t)) - default: - return fmt.Errorf("option %q must be of type integer", key) - } - case reflect.Bool: - val, ok := val.(bool) - if !ok { - return fmt.Errorf("option %q must be of type boolean", key) - } - field.SetBool(val) - case reflect.Float32: - // JSON unmarshals to float64 - val, ok := val.(float64) - if !ok { - return fmt.Errorf("option %q must be of type float32", key) - } - field.SetFloat(val) - case reflect.String: - val, ok := val.(string) - if !ok { - return fmt.Errorf("option %q must be of type string", key) - } - field.SetString(val) - case reflect.Slice: - // JSON unmarshals to []interface{}, not []string - val, ok := val.([]interface{}) - if !ok { - return fmt.Errorf("option %q must be of type array", key) - } - // convert []interface{} to []string - slice := make([]string, len(val)) - for i, item := range val { - str, ok := item.(string) - if !ok { - return fmt.Errorf("option %q must be of an array of strings", key) - } - slice[i] = str - } - field.Set(reflect.ValueOf(slice)) - case reflect.Pointer: - var b bool - if field.Type() == reflect.TypeOf(&b) { - val, ok := val.(bool) - if !ok { - return fmt.Errorf("option %q must be of type boolean", key) - } - field.Set(reflect.ValueOf(&val)) - } else { - return fmt.Errorf("unknown type loading config params: %v %v", field.Kind(), field.Type()) - } - default: - return fmt.Errorf("unknown type loading config params: %v", field.Kind()) - } - } - } - - return nil -} - -// DefaultOptions is the default set of options for [GenerateRequest]; these -// values are used unless the user specifies other values explicitly. -func DefaultOptions() Options { - return Options{ - // options set on request to runner - NumPredict: -1, - - // set a minimal num_keep to avoid issues on context shifts - NumKeep: 4, - Temperature: 0.8, - TopK: 40, - TopP: 0.9, - TFSZ: 1.0, - TypicalP: 1.0, - RepeatLastN: 64, - RepeatPenalty: 1.1, - PresencePenalty: 0.0, - FrequencyPenalty: 0.0, - Mirostat: 0, - MirostatTau: 5.0, - MirostatEta: 0.1, - PenalizeNewline: true, - Seed: -1, - - Runner: Runner{ - // options set when the model is loaded - NumCtx: 2048, - NumBatch: 512, - NumGPU: -1, // -1 here indicates that NumGPU should be set dynamically - NumThread: 0, // let the runtime decide - LowVRAM: false, - F16KV: true, - UseMLock: false, - UseMMap: nil, - }, - } -} - -type Duration struct { - time.Duration -} - -func (d Duration) MarshalJSON() ([]byte, error) { - if d.Duration < 0 { - return []byte("-1"), nil - } - return []byte("\"" + d.Duration.String() + "\""), nil -} - -func (d *Duration) UnmarshalJSON(b []byte) (err error) { - var v any - if err := json.Unmarshal(b, &v); err != nil { - return err - } - - d.Duration = 5 * time.Minute - - switch t := v.(type) { - case float64: - if t < 0 { - d.Duration = time.Duration(math.MaxInt64) - } else { - d.Duration = time.Duration(int(t) * int(time.Second)) - } - case string: - d.Duration, err = time.ParseDuration(t) - if err != nil { - return err - } - if d.Duration < 0 { - d.Duration = time.Duration(math.MaxInt64) - } - default: - return fmt.Errorf("Unsupported type: '%s'", reflect.TypeOf(v)) - } - - return nil -} - -// FormatParams converts specified parameter options to their correct types -func FormatParams(params map[string][]string) (map[string]interface{}, error) { - opts := Options{} - valueOpts := reflect.ValueOf(&opts).Elem() // names of the fields in the options struct - typeOpts := reflect.TypeOf(opts) // types of the fields in the options struct - - // build map of json struct tags to their types - jsonOpts := make(map[string]reflect.StructField) - for _, field := range reflect.VisibleFields(typeOpts) { - jsonTag := strings.Split(field.Tag.Get("json"), ",")[0] - if jsonTag != "" { - jsonOpts[jsonTag] = field - } - } - - out := make(map[string]interface{}) - // iterate params and set values based on json struct tags - for key, vals := range params { - if opt, ok := jsonOpts[key]; !ok { - return nil, fmt.Errorf("unknown parameter '%s'", key) - } else { - field := valueOpts.FieldByName(opt.Name) - if field.IsValid() && field.CanSet() { - switch field.Kind() { - case reflect.Float32: - floatVal, err := strconv.ParseFloat(vals[0], 32) - if err != nil { - return nil, fmt.Errorf("invalid float value %s", vals) - } - - out[key] = float32(floatVal) - case reflect.Int: - intVal, err := strconv.ParseInt(vals[0], 10, 64) - if err != nil { - return nil, fmt.Errorf("invalid int value %s", vals) - } - - out[key] = intVal - case reflect.Bool: - boolVal, err := strconv.ParseBool(vals[0]) - if err != nil { - return nil, fmt.Errorf("invalid bool value %s", vals) - } - - out[key] = boolVal - case reflect.String: - out[key] = vals[0] - case reflect.Slice: - // TODO: only string slices are supported right now - out[key] = vals - case reflect.Pointer: - var b bool - if field.Type() == reflect.TypeOf(&b) { - boolVal, err := strconv.ParseBool(vals[0]) - if err != nil { - return nil, fmt.Errorf("invalid bool value %s", vals) - } - out[key] = &boolVal - } else { - return nil, fmt.Errorf("unknown type %s for %s", field.Kind(), key) - } - default: - return nil, fmt.Errorf("unknown type %s for %s", field.Kind(), key) - } - } - } - } - - return out, nil -} diff --git a/ollama/api/types_test.go b/ollama/api/types_test.go deleted file mode 100755 index a9de5a9..0000000 --- a/ollama/api/types_test.go +++ /dev/null @@ -1,233 +0,0 @@ -package api - -import ( - "encoding/json" - "errors" - "math" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestKeepAliveParsingFromJSON(t *testing.T) { - tests := []struct { - name string - req string - exp *Duration - }{ - { - name: "Positive Integer", - req: `{ "keep_alive": 42 }`, - exp: &Duration{42 * time.Second}, - }, - { - name: "Positive Float", - req: `{ "keep_alive": 42.5 }`, - exp: &Duration{42 * time.Second}, - }, - { - name: "Positive Integer String", - req: `{ "keep_alive": "42m" }`, - exp: &Duration{42 * time.Minute}, - }, - { - name: "Negative Integer", - req: `{ "keep_alive": -1 }`, - exp: &Duration{math.MaxInt64}, - }, - { - name: "Negative Float", - req: `{ "keep_alive": -3.14 }`, - exp: &Duration{math.MaxInt64}, - }, - { - name: "Negative Integer String", - req: `{ "keep_alive": "-1m" }`, - exp: &Duration{math.MaxInt64}, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - var dec ChatRequest - err := json.Unmarshal([]byte(test.req), &dec) - require.NoError(t, err) - - assert.Equal(t, test.exp, dec.KeepAlive) - }) - } -} - -func TestDurationMarshalUnmarshal(t *testing.T) { - tests := []struct { - name string - input time.Duration - expected time.Duration - }{ - { - "negative duration", - time.Duration(-1), - time.Duration(math.MaxInt64), - }, - { - "positive duration", - 42 * time.Second, - 42 * time.Second, - }, - { - "another positive duration", - 42 * time.Minute, - 42 * time.Minute, - }, - { - "zero duration", - time.Duration(0), - time.Duration(0), - }, - { - "max duration", - time.Duration(math.MaxInt64), - time.Duration(math.MaxInt64), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - b, err := json.Marshal(Duration{test.input}) - require.NoError(t, err) - - var d Duration - err = json.Unmarshal(b, &d) - require.NoError(t, err) - - assert.Equal(t, test.expected, d.Duration, "input %v, marshalled %v, got %v", test.input, string(b), d.Duration) - }) - } -} - -func TestUseMmapParsingFromJSON(t *testing.T) { - tr := true - fa := false - tests := []struct { - name string - req string - exp *bool - }{ - { - name: "Undefined", - req: `{ }`, - exp: nil, - }, - { - name: "True", - req: `{ "use_mmap": true }`, - exp: &tr, - }, - { - name: "False", - req: `{ "use_mmap": false }`, - exp: &fa, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - var oMap map[string]interface{} - err := json.Unmarshal([]byte(test.req), &oMap) - require.NoError(t, err) - opts := DefaultOptions() - err = opts.FromMap(oMap) - require.NoError(t, err) - assert.Equal(t, test.exp, opts.UseMMap) - }) - } -} - -func TestUseMmapFormatParams(t *testing.T) { - tr := true - fa := false - tests := []struct { - name string - req map[string][]string - exp *bool - err error - }{ - { - name: "True", - req: map[string][]string{ - "use_mmap": {"true"}, - }, - exp: &tr, - err: nil, - }, - { - name: "False", - req: map[string][]string{ - "use_mmap": {"false"}, - }, - exp: &fa, - err: nil, - }, - { - name: "Numeric True", - req: map[string][]string{ - "use_mmap": {"1"}, - }, - exp: &tr, - err: nil, - }, - { - name: "Numeric False", - req: map[string][]string{ - "use_mmap": {"0"}, - }, - exp: &fa, - err: nil, - }, - { - name: "invalid string", - req: map[string][]string{ - "use_mmap": {"foo"}, - }, - exp: nil, - err: errors.New("invalid bool value [foo]"), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - resp, err := FormatParams(test.req) - require.Equal(t, test.err, err) - respVal, ok := resp["use_mmap"] - if test.exp != nil { - assert.True(t, ok, "resp: %v", resp) - assert.Equal(t, *test.exp, *respVal.(*bool)) - } - }) - } -} - -func TestMessage_UnmarshalJSON(t *testing.T) { - tests := []struct { - input string - expected string - }{ - {`{"role": "USER", "content": "Hello!"}`, "user"}, - {`{"role": "System", "content": "Initialization complete."}`, "system"}, - {`{"role": "assistant", "content": "How can I help you?"}`, "assistant"}, - {`{"role": "TOOl", "content": "Access granted."}`, "tool"}, - } - - for _, test := range tests { - var msg Message - if err := json.Unmarshal([]byte(test.input), &msg); err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if msg.Role != test.expected { - t.Errorf("role not lowercased: got %v, expected %v", msg.Role, test.expected) - } - } -} diff --git a/ollama/app/.gitignore b/ollama/app/.gitignore deleted file mode 100755 index 0aa2479..0000000 --- a/ollama/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ollama.syso diff --git a/ollama/app/README.md b/ollama/app/README.md deleted file mode 100755 index 883d7ab..0000000 --- a/ollama/app/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Ollama App - -## Linux - -TODO - -## MacOS - -TODO - -## Windows - -If you want to build the installer, youll need to install -- https://jrsoftware.org/isinfo.php - - -In the top directory of this repo, run the following powershell script -to build the ollama CLI, ollama app, and ollama installer. - -``` -powershell -ExecutionPolicy Bypass -File .\scripts\build_windows.ps1 -``` diff --git a/ollama/app/assets/app.ico b/ollama/app/assets/app.ico deleted file mode 100755 index 875924f28e3f0e63d3f1a9b42e7fc0864d7f7ee2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7502 zcmYkBcUaTj+s4x}Wfs}8iXs%*AREe7P}zG)*?Y;9A!P^%h=>JbF9BswS+Ws?vJ_bY zvPAX}WJCML@9&>Cy?P}*$w^P18n4`&Y>fyjE%2{Z$N^8 zV`Fi@k(@e$$IvgixHABC^w%*z>@FJCdHdM?9W~Ah zhhYcYfOm7C>Xz~k_4TMqnN(ll0CkpY*I%_j0Yf8(QDkL=#qHId6HQk=WyLN9DpmsG!uS*?}IzWpuu7d^J#@ly11d5bgQ zZTrw*8t;i>%mKHr`4g_^`$$(qwVpDg+;J?nHyX8d=?rdHH1j=h z8l{u>6})eRUasUP#;D25m)Ks2C8qqvwAMx)mw(k?D=m#{8KG$Aiw_?w$hnhuh8yC< zt|os&vg{6C|Dm5pa@Y|a`1{i@u(u7i#ijo2{~MJKd&GfmG- z8YgoZxvN?bJMEHfMc|hh@^00;_rXca514K9Fa=*+v!9|7CM`2A71jwg=en~WL%VnH z%R82nbxu2cYH$CD`zlOfYR3+rv~OU$1S;G`z6C>U4FSfF%)E8ItE;!w9L7!EPhre=4Tffjm;q#|Th0~YJ25E* zA(3`SiiA$?H1$gALMi?Zmy8w=x+_%%It`!}zhx?4}9H}jAt%!N>$kIX`X<&9K1oc`6oU8204 zcJG&0C`rtDU_tL=8aZG(qLL0en;=Mc_iF^{;$x*c(R)O&X$LOW6?v6yltjAt@ngR! zZTk|&<@?L_fLiS zAhBWV2h|-DB`kyO^;Z=Ih^AS`-A|2VBc@#i-tL#!g$OSpl+Qai;)?*HaxLi~b&*6q zC|^+#=E)>7>J7RnjeYKxtsIe5-GJ)6rT^cG#%=w`t4@vT+_Mxh>-p=}VHT;2J9W?a zW-Q$RBsr?%`^B$Eq}oh{P*lvA=|sE&%cbZ(Wk9o;7ozdmA3QXZI;bG8f}1fHjLDc$ z`sF%mGmk-ub^gHATuw1c>Mr)|^7Lyutk*oVP?;Z1r`5Y0K#P!0* zGz@pr)T&RSD*^HcF(KW1i_F?u==+P40vWAe94CJD)C_{A@S z+Hlst%>>g7nWEc*I-M&9_7=`SGPh0HGDS~3X};`Aevlk>FrU=wL*9Q4HPdO$WYovx z$n84&4s&C5QNaM3<>#94AwdMQ$Fw^lzrH|giH&74N4F4>B`;|gMfA03a_iCR~kr1CE9epmJ}THF(U`OQS~ zDp8k?XzR!(p3Wy=Q;?~U2VNc49RwS4sMBRVX;9;RF2(-+?RlR7dMpceDc1LuE}HX1 zb%@H_xP8>FN!E`sVFLQ4naHVoXGfrsbbH7_%!4NCwY4x>9}OpM;<55%iltAoerMGA zwuvb0zB6W7>Nk79PhsH&K*Ute9)cVBipXBBSr8$%A^PszH9zy5<3-m3?~P1cN#J$> zg){@5o6fYXlUG1=p$4zvu!9)SlxhD1UAmVxq==$B6@Enx4z1?<7=Naw;C&JgNG#X7 zwQX^`O;BhkWrcVIJn(3{y$oA8yXNalKN8l3mtlj(1DebTDp z=+Kz1?G4+~&o-Qq&+K}==NfLBcu~jc=fCOlOpt!D)l@PP)V8ZfGt@-VKYi_M_y>hw zotY7AY-WU^WUEHJW92<{N!UIcVyTlGD6%jbl%PB&Dx68n)9Yk ztyyxL4=X*{dw#M3clzK)CZpV=TNuljv(FCZekE9w0W>;zpVgLhDx8*)L!>W(d$N6u z@+g>sDpx$d8GF|^>n*O2X?H-4iHS;xXSkWi|v%HehNwn2VFUr<|Wmr(sZ-c^@@_lq@=NmUGJVsB7JSU1iNWLUvp zuSp}raNEl^U+Iq-V?K2olcUQ;7~`K)JPS{l{9*XlMyLXfUu9UNzkBR`Rngqm_Bj`S z>A3rZ^wv^i$CW^P7(TJ%YR3~Z>I6{ly9ssn-&RbxBJVJAs;HUWv6~l?D&l__g1byV z|8&Zb^OmBRKph(=US;~*KThU&pBPoI2J~l!#p4vfF;S@OiP+RSF#tQM`ao$y0GWL0z z{Q;;+kLX+FogM))#r4Qqe(z_`v}&Lq_wB^S7|9jGVH%&AZbe$HQx?%pkdZEGNO@cF zqe-JO^=pqA&x^sqo~xP-E}+-BZ)w24U;|b=O~B5 z);PKtV@q^1^p8ROn?gz3^BRh`?`L}t;`l~5NcO*SzoEeW#@N4*8wDQ$b`FkQd`PU` zW-~!nxGu;%w>GJma;^H&#Wa4wH>OKBGnqdj|F$NntKeJlxU(l^t67B^rD%~s z!|aaC>mo#)OS47Gv+f@n-^`55CQ9r4r+54-Qs$pDZ$HXO8(Q<3ZIRuWbu%JEA#+c@ zy)T;>EY)q*fqJvnjUH?2F~-5MqFc2AA23ujM5vfX2B2ts$r(`Rxm5Zq(IkgsXISk?9)B`_xCc{wbXVlAj0ngD^lE8RKmum4%jiE zWd_+s&3tI#(zwo(ZN+PEPsF96oN*NL(9Ct~_Up1BFZ-9Dh?F2)Sp-S5wAJ+ksv)^M z2&;}~e)>%%K4%gkX9q;a#>UxcHQJl~cXxMp%~oeU8b>ylaJcqEQ7Re_1@t#={i&3; z8MpJQYk&g&QY;l)H10XMwqoXLVPPSco8Ixa2qdPxDKeP6}Tt zRfa$;%z*yHTvEq=Hv;@^5T({kW@#(ax*xDb_l=L#45A<>@LzqU%k`7lcZ;#6Jc%ok zVUEofW@)oA;rL{!#EMtjKQq%UPa)qwl&#WuYxo{)qfDP#?hrJ+_4}!>^YL-CHIsi! zUx|$?CF|j&&l34qiWtm0*QQ_oGz4`GOSZjP8xwEe8C=()8Iv>Ykd0{|cc@DrhqOGd z8rb=oGGXUBAYb%0c>he1aI`+i(2z@VZg$qZgv|kzGe#qo)w<9w#uG~KtwQF-oa!JAqp_iaz@O?RQWdd|d^ z07>FZ)`5n3ewpG&(W;qBv+v|zWlR0_R^9B>a2}9f2NZr16CPK+>{`QwAn zc#Yft%Hzg&*JkN_|~@5zUw8Fhx-F zL6jmQZ_hy{ZdhcOkM}pb9nw~DySg&MyQN@Q(N}u5rRBla`P+u!Ctn)%e?U^avjelVJ=f*?I|464Cq9f3C~#E!G0s>%e!V7R5iSI*f*k9 zH$%}nU#VYG8Xq4&(!O&&2Kz-eQ0C&I6hOCC{Y^cmse~=KZ~O>tkl0wbMWJH+dl%uf z*%GoXHl2xoyj%wb&@3kHY&t7FGPT!`y(xP=G3-oQnNmr0z3tS&@q1+O7y>>Nshpgg zFOH>O#@C9VZexIyCz0-eI41)q-p&WSZ1YJH4;^;-zTkNg^_H@q_%VlQ{TbWH$KahK zE^_5<$@;d>0Yt(CHPFl)=>WCy;dTP^Ko5A!!Dn=0AT5-t08&Z*Q``fph6`bf19 z8g$z7b>9EY)I_q#>HcUym_jyXwE@lvR)-`q{XCvDHtY1X`39RhQVAM?3U4Cmi{krj zL62%(XIh(2W%v1|ooUqz%N!TZlkqPNyr@g_VG%lCEl2Y{)?bTR%_LGO+M(DigjU_* z(e7j3?Gh)nf!&#z3LocYWssZg$s3c1OZ0?TK2Cl9O;RZ~B=imfc4s>6WnrV!1?%Zp z3R;s?V1Yx0lbDzno*BM(-6pCo?B#G`ZPjQv2bkf?YR?l17SOT5NoNTSXL~*-UW{z9 z7ak${aRpB98{Y?}8t@NegCQa(@WXV9RC-y=h`!;m&^&wJ;mPZxAooxQ>0%SfgihuX0o)T-WA>S;sCXgb}n+pVU+V#Bn}O=mY4IjFoUY7tK^(fJFon_dZ0HK zNwvQwkG0U4oW5r_I6)%R()Px2055Hh4l z^&a9SdcEb=+aR_>@cFm1ic-Y$ULf4RcondqH9-ge+0cObludD(6!a_E+9rm}Fg7$| z+rRZr+)behXpsRJNo|M4DOj4z_GO$o0Atr=?a_L|5&>6a?FWwY8}|10YUVwH1|uUQX+&rI`!=MPzkiJxK5w-MwK79_ip@~ls)+% zy-Jme6>E4oj0jG8R~14Eh138{H2;1OR{(@cd7NOSM2krmi16x;g~Fm}@6n;*S;CP< zfaT{h+Nk31HMB8;8AdDXX zsvi%9U7e?Zr|X4};C?n$pT7h2W)m`pqyKBtl40>Ua}6Fcw#sg9cdQEbJPfG^D9}*{;anPK3Mm4ldtlKD8OD9F8(4Q?wNgk_O{A;; zb8ha7fKnGTc-7Qlrvyi0ymBm;=v*=Y?tuXfeOVcwE)>cf6FPux`0(l>`o`99=Z$~q zjQNsw1WHXs5=J#Dfp-aM0D#5B^KiLQZ=aRn*JZ-Otb(@(LYw(QJ_0~DWtWPbzK#>t zrQwPA(_j0($0V0v^L=*xfPkNOP+j`0GAU2z&q9m=bE*BTCA zeXgilcs)F3txiFhf=H*k5K9{|mLwZ^{q#^i8hk>Qz4PWMVLz4^*G;_B@~^4r0%8w- z&zhI9^mSho%Y5C!ih5en<{6?uObEXC_#sg@dBfC!%}HI#y0WtJeV0Pz;u2AwN;C@c z2$9a_^khlZdo1A7UP!w+a3e}8T=at6fYk(&yZDDUb&o+&eSp8NLvd9o?Chb&WiO_c zVsELH2(?27wl2mhgq-d#Fr6&=F5Xd3e@R}HI;*|S&bps{XZ zE)_ItlQTq1FnvSAYd>U=zXW^DPs;&8cQMe}vWgK5lQsPo>@+_u1@0a{1o*gVzYXNW zKlNT-?S*MyI}<0pYJM1E2=vJmid=`NdyVWpJ88YQ~`2CdHNwm)W+=?3kO zRdsX;7On|o^ zs5z9U1@wIa891jU$rZc4T}hHcJ!YPd!=tW{=xE2+5h40Oxcj}CE5;z@E8Iy(7}qcA zCUUPYPITyU{PXtH6%Kshy)W!u*sxenGR0X3%x!QUg`JP*w$s+SdYn=J(S(@nB;P6G zI;a|B={Otq96^Q2>iGQc@EN=08LRbl;8+CTCPVgD6GAAF-g}|F&U`ekt+1N(Zge#6U{YH&O`hYy5+%qa#M2S;=WsTj5G| zpt5W>D5v>PQQE2}>z+JvGbQ%nS&w@WK1lmrq4MIr#D>cy!J+!10jyHE#+fKUHF zMkXjjF!loi5neWzTUK~Iu)87%Oq2ZuJg)IqY8Mfb7d*uW1(jflcGfh<=|1Kljco}nA43q~Pg0H*ImzTm1q+spd z|HTmAFdP^bHY(8SbrUoK4~_-?9eOO9)Q7Xrn?w{P*{54jT$cfD!aq=@X5}t@MWVqv z5EWKj&ouS)V3oY_vir-7n*^pSx2Ld+`qU8ubdq)Uau=FFl&AjnNzC4>2{RjF!BH<& Xe!DrQxH|;C5d}2Vv{WmVQ4#+K%p*A% diff --git a/ollama/app/assets/assets.go b/ollama/app/assets/assets.go deleted file mode 100755 index 6fed2d0..0000000 --- a/ollama/app/assets/assets.go +++ /dev/null @@ -1,17 +0,0 @@ -package assets - -import ( - "embed" - "io/fs" -) - -//go:embed *.ico -var icons embed.FS - -func ListIcons() ([]string, error) { - return fs.Glob(icons, "*") -} - -func GetIcon(filename string) ([]byte, error) { - return icons.ReadFile(filename) -} diff --git a/ollama/app/assets/setup.bmp b/ollama/app/assets/setup.bmp deleted file mode 100755 index ff58b909a1ea964c0436d337d88dda6786043051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77418 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 I*cO4G0Lng3rT_o{ diff --git a/ollama/app/assets/tray.ico b/ollama/app/assets/tray.ico deleted file mode 100755 index e63616c5738a8803c6c9f04ccfd4ab00e22cc88d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91014 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 diff --git a/ollama/app/assets/tray_upgrade.ico b/ollama/app/assets/tray_upgrade.ico deleted file mode 100755 index d208305186492ac3bb4e35de40c42775d15443b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92898 zcmeI5&yOU@RmW>~W_MWcvePz}Eg7WAwE!cnCAU|AIoM2kk-?XhM}kF2AWfZ+;NWTg z0aq>J0*9Uc2TYBSI4;xwfK_urKCSv6z^dVnw1c?pVYSKkla((gDmo%FDl4lht9qXF zIx-_8-tTx38JU$m8r>M(8h!c8BbC|c`K{6DPe-HC+ix$=fB!3^(I37#8vXEx%kw|_ z(P;GdUmuM={BU`mzjb5uZ+|ly{hs=W#ORws=m7sDTL1aV63dF!KPS`aG%JcCidDV>(yY%|n>A9dl?u(0y;?bi=W&g*IAD4B|gf`dJVPT!Tasgk{ z0sGRAGSBk@`lqL-rJU%fzPZ<*(@S``08P*bXsUfiCl8|W;nKji>NofLx~EUzfiHZS zOeZz|RG7J)yyMcY&_H+mfgSOeovZ!A>*JrE;|F-^!Xx1mA#zX5o;q%$QQD-kS+4dj zT;elTK(h^KgA6|0SH-2!A0wlux2L10H!2*d1nvB$jzQ=Ana-c75BT4|oR0oaNWObp z_@2=6-7O`+e|~j|s*b^lE{xxK=N%HpM)<)8ACz=N4;`VK3bZfBf*XJ991}13JKrpR z`mNi=N8f$DEdS)|w>}l!sW3&BTjH4@grAa2nXqyd8 zhL3+x&R1tGGMppBI{qMsfBgM7lI*}bK=h{#GT@6(PfkwOwgc-7)3vFr?9e2`eaWzv z4e$~30e)`cZP$MG?O($VxiAJ(T`0)$>jL@QUo#nBE4f~c&lrE|r^0f6T2}^aaZkA^ zCI|KJe&r^)>QvYSQ(bJ8fq9#J0J2VDP6bLi{@}aC&%S-T_~g&tEajp6`S)J8wG+N> zgEKWK*D57Z?+?7QEGvjvY!5OA(}!bZ0Fa4s#k@~Rd)f#yVH;qlV2*-5w9wrLaul*4 zpATHCWWW!pFjvEJJ?GLxA9OWfJ!9(->X4Cs<`-*Mt@*e%6{f(68X@l$TF3xB1L6Sv zki~#=Uk2<3J>g840%bhF&wv;p7lR^D>dQ5FaSi;t@(Qs-t@&* z&=f9&sW4N+;=zLlD{;|97UI$# z`>i0fn*hFkADz#IU7(bKTnt~!b)h_HGFgtm_O!=tVhnbbA)`Nf8906|>)}DXA)^!b zD}5>%7Am_yrcNvKL*-lMl5#%bx`$=GJEv6FyUI}d!tyQSw4ygx$+i2!N5YwKD$Iqk zK9{=I6_CGl1@`7xc-}$`eg)&h$qQ|LnnB0NbXmZ=?m9tk;agy*Bt-Kkor)DB8nYDZZRJXT$y3Vx`DkhjL> z3H^#YpOqzhMn4q(qwq#$wp;IwM!)gK5>>qpoT@QCDDnOG-=Aqv?F~QqAKSD%@1-~X%k-zu-&``Rs&6L#r8PbO7 zj!WGOHl0Hyc97!Wtg8XkFBck}mHYc%27Q1CIe^?2(y2>bwP%kGnXn6-s8ekNTlWV< z@1@GtR4M<@}o-^$koYcl;yU@ z!?tX|vy)1POl23CtCP`K+2iSZEU@qOlizx^_pz{H9OSP4?sJm9^@rZJ@MpH_9C~H3oWL|GZM0VAFqq9p+40+aL^rhF@XBi z^TD>)M`j23aKF>n8lhSnphuTEfj)IEbe}1jyxS-(7JmAzwD%Q4zPGxM-Ywr{K!-D7 z7s%A9wgJx^b_Mo4g!cnXpLI*#C#dqkyo>TxpS{@tTigCo7dx;XsPtb*mo8(#%(hn> zU4E!&EwIHx~8*a}g=|;)`_v z{n5wzQ=$VlA?FzqA3WbQUt4>g0fzv4@csn*O(6ENIJ3T0d8)Dxn2JcPN6IsNGxwhau72JN3nfUDsuw`w7)cXaS+vv;jI)JUrev~QTyeD9?p7&*diVpeJ zXqV4{+vGBz5c?q@e$kKT&>_J8#c(8f7oYVFPeicRt8F~EHt_Si>1p#mu|WF}*mxk9G=Up4m7L^)OxPFX zB2?>-Z(=f=oa8p^gTH<7{T8w*G*aUL`oxp*tjd|nzF;K=LOS_6a&A7P^nrN|nW04) z%9*a6VzK1X#V^KFikm&M9*n>`k+>>phV(%Wafk}W z@o@Wa?DDK+9;@6GauG0_2L0v6thGfJ!0bYO>idfHHT~&F3^eg58C8FX1(TsFFH~*{ zV-cw7hGNnk`_|Tc=f@|y5fi4D$!}{u`WX#Mn^OY*4f+Fmc6~u6LbVMz9%3v6=A5Zy?Gq*tD^_o=)?E7Ng(|D@w`{2>E#{;q-bGk!o04<|a`CY*}+iXC)b%D~!$xs!D= zV-wr-0jx=&2VLlM?Bzb!29LI>yhA%`2eXHjcK_Jb7Q|PBzOL>Z?@E6&MKBgjcPlr| z8G-rU*V{ecRt_+o-7+&BDJ@PTW3ybpcgYu_`(^kM7x47%jj+X3xGP{R)b{uH)&gsl z(hlpaDMGnEbg$^jq2t-E3?M$au(pBibGTz3Ke=r<#((J66ceoXWAPN)FYt23Tzqx~ zxfs=PcnwGmy3m^90)WO9NpAgNy>Mo7H|D24tuxnMBtLzFjAL8Bx=426d z@qSk(9sA8({_foGjZxxz6F67rT2D781m@q9O&E3PJ9cGbt^=6o+uk8e1~qY0On^~-NlRL6In`tn;ARlR$B+i9~rekx+sw>gTd$K^LS zs`{(PQ@W0>(u~!Y&6nThAaDdrnXew-o2ssAGbxYxqxCFB!JpORvZ|_I9zQMHILDO@ z-TJB1W_diJSm9eXsrdGF43n<%Kcnl-rC!fDuHr-=EYT-Vmi78rNqy|rZ+4u$V)Q>7 zegCc<JFE*YEhZqZ)KjnLjn4-Z1bI^o9D5E3Ju}_Z_n}-t zEClkxrEEWhx#8NzfbW0CYsznwLq1NaBQN~qH(&Mh0dqqp+$ZE>?#or5A8Q`){r{aW z-`ptgr^JA@ss3L@ZDZMg-*Is5V!*zYZ?RAAH~;LaWZh`|tCD$PUyzBhFHe1bY->WE zd%Mq8xA9%8)Hn*n!E{eSz?!7?xqr<4@-czC*T?+d*Eft({qDC5%nSLR;^12B5xMV| z@SV#|?)!XSZgS3C9`$l%ITzIS*Gd4PR?cMj;|d%v6b-R(;(dV2`tJ;cE* z76Zrfyui%?+yl5i7{W382aXRGdx(Lt!{3#qJZ^e7`w()3p98kJ2e3&z?Ku~mHpPJZ z9^oPQ+?UaP#}GSj;-_u)b-oqM*qaM?4GS?W$Gu`0Ho_uUd_Y<=T6Q$KG?Jiyg)Q@mAZ) zJ+|*|xOP3HWAc})&%WOsYm2+;|IM1rQ^~#y$i&2WUMb0?hYs#LghSsa^7e=FT?Bx5 zoHfP3A+7`cn05Dy_xT=iTMl3k%kc&KG`oVwV&w9!j}LtwuvqZtgQ2`j>c@n)H#FT< z0EiFIrfR>t$Bdt20r$DV5T74Yh-n;(NoP@1Y)QOt|k65a&b71zrxA;g}sk zCO*L&Kz(2T2WBX73tICe@x>G)&ZGtSCENOGzJcJUnmxH{<@&c|AhAE@J-L1 z|FLa;nC{B?6`x$C@xD^VYTY{n)i%!2i3R1EhKhx&8)Y;1J&#N{w0eJp6CZ>@pt&{ErXt#XcYx(`y$4#0qNz zKMsESt=G2xJLHdl@FoAZh1mbWKAd0i%vA1$@suO`a71oyY;W*1_C-+iq6ypi}}+ilC{Uv+$BYnB* z^L>1S1ivvZ{kghH&ZcX`2H&4bdG-ZwcTd@;%UH&*#02*e%^_w0e!Xw4<0;-@->;TGj_-R$kK-RAa(4n8wcyy z0eMY_NSUjCD8T(mR9^D*HlS(zlSg@OjlVYm#v)_0X*}}1%54C7p~0@K!B~$E2^JD2 zC^P=(8=A%lw!?RQ0`y{QJmO>1So38~mXylL({qM zwQr1%@l!dZwSdGap>aOwGZ(~iz_$HwF&xX$edU6L96-Ju+B{H&LHxZ!H7NR8KZSAt zb?X58hx7r-@$1eVq5HPJazVm6mz+CP7)vl>G>V(94`X9w-MPm1A@>360DAa(_HiHV ze-GW~QJv>1hYSk|cf~$dx9)iL{lfS)T2^+MXZ&Y<>&5_b8GpB2H=p?WHQj$yeC8^L z4y;vz_MsjfH-XUj>ym^0HGY@hLlV!vuA8h0=8; z*>$S(Awn*p8vWlTXZyYl-50L2#)$dfWM5~^8k)N|jRDpZ{#wOkb4qeSCL9{fB~Ua5 z&}-B667hhILwr(fAM5MVOO2;cEN;5iv3N&L|GveQu{xfq91^e&2>OP4Y?I<6vq4)K z8Yija*R?Ij{+ymVSNZ+WlewWU2;Kj9HeTp_NHCQ!(HQ8mW^1x#Xde}Sro@T`BXcOW`e%Ll3 zhsoy3;Lii52lce0kFQ6YtT8?!CkS0CQ&yD9cSzB_!P~ImTV}lrCk5p(|vtti~COZ=c>)6?7HkD2M{B`6ydNlFm zT4?R***e$xz9G6NK+LBCHkKl-=*CoRUWN|5v0op+dNY=v$n~yF2|inUue8N3XZsES z@t?yz7j1DsfBZ#EvUZQz9~rpru1Q_q?s3Tf=#mlx^j!yHYoAJ< zxypS*(Ek!D`CiNH5zDvGG7QB4{Tb`n*4m|%v`^vb)1pr-j#6U4Uq6`sv9cw`2OR_J z=3sKKZ*TuRW_#?%wU)fuO5f+_pX1{u8PM798=^X|t1EtN8b_&f3w-;I z1?c&6Kk|m4DR;;6Scs0*wTz9Uivje;*KS@X_jdWd8L>c2xwJH3qA}}VqaXdd#ByIc zV2=Zcf#`1yyVwq$4am8D+~-3BSs0(}=@V0aTyW0*57!y1o66p&4hOIvAQuJ4R%-4x zd%Y~f7HFDVWcwlP7tdocKpuSwn_Hk|Z8MYo_YKi~!d*PW+1$dzr{K?9a=4p!hp~5HA z)U#zz2>;KA==@5iu}Wl&BJb9|gt!G-?gh=RxokXSSV%aNHCVpfGYH23o*6KV^^NlF~BKDh4dMAmqjvR{J zhXBa2Mozz?OM}icT{{+FUO=C9^lxoDl;;o~$9J24lVfqdr^l1N<6z&pfO)EKokVZu z+3lE4d!G~boeQ><11^rq>7Fj1>b&=Hv#)28to^p3k7zPhjuA2`wH2G~V|}=#Il#5g zF~&gN6a&ob*p+)L`yI$SYwcae0kS4M+pYbHZ1(#Vesh7IV3R#`EfXFajHOUeZ|vCy z++WA~TRpZ;{Y_vSzu0x=ofQAK%}?xanB0*vSN*ZUnG_1@o%-HsN?yP}%+uR|#OFF? z9!udLvqx2*t2{QCN}*s3u(nPC?g3&n{Ca4TZ~FkobV~f045`15ZJ{|9y<>xODHQZ! z>iyk1F<`vt(=`_8*X7(>-`83QlkVb?L>`fD4< zFJnMf4Z~wq2gg%t46O0KO^{EFf8X_~G0>8G#**vUU@C=zz9A>3K#R@hqQ8jo=(!#~ z(Ptm2G2OD}7>mcT!Bh%u6axu1;~DitxRvJ;qKogxLLhpdlN!@4drkM3Y>w*hSlR?* z0N=Jj!oHeoGmC}jSdGaNsh_KUEOg;aC)?B~cbOf@F**fpMtvJ_PuJ96*D_%Ua#c=* zb730|_d4zIb0!Qyu1dH4%5mGfZai~n>aS~=@Yvu~3Pts9yKis#HW#@+1;`J`F&5(A zse_!~7jiuXGBt|o)3z^lad8ptThUFC;Sk$I^=^B{!aA$L=JP!nBf9QryEkb0P1#~k z`s{*jbbiJrP0+G_I^Tux0UpF&FgDxPg)RF-7XeCp(hgXOpWU8Uy^^AOs094c%jfOo~Nq7Mep7 z#>{-r##+R5irw?J?02%p*jG&N%9Lx_jJSx|xT@cG-kdeb=jVb0i0NI#!Fj6966{5M z?0d}QP5St`AYon`i{7zACIzEo8=Ki$swHPaV?GdLEt+()Z?7b*1Fpk7U@n_A*^D?y z@INt-8^Jx7WAR6xD6+rNaxXyNsqnf$CPkz6O1w57n6Va#a>w+(PC39_H`~Bw*ef$a z11V1>N6fz|_0xgqu}d*BFZn?GCYxR zP4fHK7HXdjS)m=smWxMf91Pw6n2USWnb7xj=zO7eneZhn?J$=iLUy7KTaAT>1P>)_ zQ*6(4Jv$_Yb|h;qK97V?D&%-9JX9bjjD`5ybeifo6TXC(78ryDisIP|Iqnt3RA(!7 zw*z%ItnTTHzUsB?>()&Ib$0`GcLH^{6YFjU+TEz?o;mV`>PCTf!Me#(H<#Y1s(bG6 z7~Na8ORf7X(6_bj?vlsnZr`eIrEf#sihNbOP~9_^$Gs)r)VimEzAJT;sah08r@CU< zm%lXx>dfcUy3uH4@zPdj@#nU)ICbkRp53~80aF5P)tM1tg7WG(7t#e|d z9{Zs>C;o00l?_65PT#tnQ&;mymG5alH@B|Ircr!nRYWHmP0*cC} zp}J5Ugz7?Z6{>UcWIdOC@j{e4CW}*d*Xp?o3C2?AP6Wep9Y;>>@kg6{SAw?v;``JQP^V zI;AV~Wu$JR7Ed+H)a?|2%Q}Uh^;Mltif1FIPFgMN6q45Ni&9aA(%lzzMM=E)Y^81r fA=TY;+C7C(@kPmfx-?_)oCZaKYQ}@Z8ff?bz>S61 diff --git a/ollama/app/lifecycle/getstarted_nonwindows.go b/ollama/app/lifecycle/getstarted_nonwindows.go deleted file mode 100755 index 2af87ab..0000000 --- a/ollama/app/lifecycle/getstarted_nonwindows.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !windows - -package lifecycle - -import "errors" - -func GetStarted() error { - return errors.New("not implemented") -} diff --git a/ollama/app/lifecycle/getstarted_windows.go b/ollama/app/lifecycle/getstarted_windows.go deleted file mode 100755 index f39dc31..0000000 --- a/ollama/app/lifecycle/getstarted_windows.go +++ /dev/null @@ -1,43 +0,0 @@ -package lifecycle - -import ( - "fmt" - "log/slog" - "os" - "os/exec" - "path/filepath" - "syscall" -) - -func GetStarted() error { - const CREATE_NEW_CONSOLE = 0x00000010 - var err error - bannerScript := filepath.Join(AppDir, "ollama_welcome.ps1") - args := []string{ - // TODO once we're signed, the execution policy bypass should be removed - "powershell", "-noexit", "-ExecutionPolicy", "Bypass", "-nologo", "-file", bannerScript, - } - args[0], err = exec.LookPath(args[0]) - if err != nil { - return err - } - - // Make sure the script actually exists - _, err = os.Stat(bannerScript) - if err != nil { - return fmt.Errorf("getting started banner script error %s", err) - } - - slog.Info(fmt.Sprintf("opening getting started terminal with %v", args)) - attrs := &os.ProcAttr{ - Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, - Sys: &syscall.SysProcAttr{CreationFlags: CREATE_NEW_CONSOLE, HideWindow: false}, - } - proc, err := os.StartProcess(args[0], args, attrs) - if err != nil { - return fmt.Errorf("unable to start getting started shell %w", err) - } - - slog.Debug(fmt.Sprintf("getting started terminal PID: %d", proc.Pid)) - return proc.Release() -} diff --git a/ollama/app/lifecycle/lifecycle.go b/ollama/app/lifecycle/lifecycle.go deleted file mode 100755 index ab624e8..0000000 --- a/ollama/app/lifecycle/lifecycle.go +++ /dev/null @@ -1,92 +0,0 @@ -package lifecycle - -import ( - "context" - "fmt" - "log" - "log/slog" - "os" - "os/signal" - "syscall" - - "github.com/ollama/ollama/app/store" - "github.com/ollama/ollama/app/tray" -) - -func Run() { - InitLogging() - - ctx, cancel := context.WithCancel(context.Background()) - var done chan int - - t, err := tray.NewTray() - if err != nil { - log.Fatalf("Failed to start: %s", err) - } - callbacks := t.GetCallbacks() - - signals := make(chan os.Signal, 1) - signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) - - go func() { - slog.Debug("starting callback loop") - for { - select { - case <-callbacks.Quit: - slog.Debug("quit called") - t.Quit() - case <-signals: - slog.Debug("shutting down due to signal") - t.Quit() - case <-callbacks.Update: - err := DoUpgrade(cancel, done) - if err != nil { - slog.Warn(fmt.Sprintf("upgrade attempt failed: %s", err)) - } - case <-callbacks.ShowLogs: - ShowLogs() - case <-callbacks.DoFirstUse: - err := GetStarted() - if err != nil { - slog.Warn(fmt.Sprintf("Failed to launch getting started shell: %s", err)) - } - } - } - }() - - // Are we first use? - if !store.GetFirstTimeRun() { - slog.Debug("First time run") - err = t.DisplayFirstUseNotification() - if err != nil { - slog.Debug(fmt.Sprintf("XXX failed to display first use notification %v", err)) - } - store.SetFirstTimeRun(true) - } else { - slog.Debug("Not first time, skipping first run notification") - } - - if IsServerRunning(ctx) { - slog.Info("Detected another instance of ollama running, exiting") - os.Exit(1) - } else { - done, err = SpawnServer(ctx, CLIName) - if err != nil { - // TODO - should we retry in a backoff loop? - // TODO - should we pop up a warning and maybe add a menu item to view application logs? - slog.Error(fmt.Sprintf("Failed to spawn ollama server %s", err)) - done = make(chan int, 1) - done <- 1 - } - } - - StartBackgroundUpdaterChecker(ctx, t.UpdateAvailable) - - t.Run() - cancel() - slog.Info("Waiting for ollama server to shutdown...") - if done != nil { - <-done - } - slog.Info("Ollama app exiting") -} diff --git a/ollama/app/lifecycle/logging.go b/ollama/app/lifecycle/logging.go deleted file mode 100755 index 9985fc3..0000000 --- a/ollama/app/lifecycle/logging.go +++ /dev/null @@ -1,80 +0,0 @@ -package lifecycle - -import ( - "fmt" - "log/slog" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/ollama/ollama/envconfig" -) - -func InitLogging() { - level := slog.LevelInfo - - if envconfig.Debug() { - level = slog.LevelDebug - } - - var logFile *os.File - var err error - // Detect if we're a GUI app on windows, and if not, send logs to console - if os.Stderr.Fd() != 0 { - // Console app detected - logFile = os.Stderr - // TODO - write one-line to the app.log file saying we're running in console mode to help avoid confusion - } else { - rotateLogs(AppLogFile) - logFile, err = os.OpenFile(AppLogFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o755) - if err != nil { - slog.Error(fmt.Sprintf("failed to create server log %v", err)) - return - } - } - handler := slog.NewTextHandler(logFile, &slog.HandlerOptions{ - Level: level, - AddSource: true, - ReplaceAttr: func(_ []string, attr slog.Attr) slog.Attr { - if attr.Key == slog.SourceKey { - source := attr.Value.Any().(*slog.Source) - source.File = filepath.Base(source.File) - } - return attr - }, - }) - - slog.SetDefault(slog.New(handler)) - - slog.Info("ollama app started") -} - -func rotateLogs(logFile string) { - if _, err := os.Stat(logFile); os.IsNotExist(err) { - return - } - index := strings.LastIndex(logFile, ".") - pre := logFile[:index] - post := "." + logFile[index+1:] - for i := LogRotationCount; i > 0; i-- { - older := pre + "-" + strconv.Itoa(i) + post - newer := pre + "-" + strconv.Itoa(i-1) + post - if i == 1 { - newer = pre + post - } - if _, err := os.Stat(newer); err == nil { - if _, err := os.Stat(older); err == nil { - err := os.Remove(older) - if err != nil { - slog.Warn("Failed to remove older log", "older", older, "error", err) - continue - } - } - err := os.Rename(newer, older) - if err != nil { - slog.Warn("Failed to rotate log", "older", older, "newer", newer, "error", err) - } - } - } -} diff --git a/ollama/app/lifecycle/logging_nonwindows.go b/ollama/app/lifecycle/logging_nonwindows.go deleted file mode 100755 index 205e47d..0000000 --- a/ollama/app/lifecycle/logging_nonwindows.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !windows - -package lifecycle - -import "log/slog" - -func ShowLogs() { - slog.Warn("not implemented") -} diff --git a/ollama/app/lifecycle/logging_test.go b/ollama/app/lifecycle/logging_test.go deleted file mode 100755 index 8d5cdf6..0000000 --- a/ollama/app/lifecycle/logging_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package lifecycle - -import ( - "os" - "path/filepath" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRotateLogs(t *testing.T) { - logDir := t.TempDir() - logFile := filepath.Join(logDir, "testlog.log") - - // No log exists - rotateLogs(logFile) - - require.NoError(t, os.WriteFile(logFile, []byte("1"), 0o644)) - assert.FileExists(t, logFile) - // First rotation - rotateLogs(logFile) - assert.FileExists(t, filepath.Join(logDir, "testlog-1.log")) - assert.NoFileExists(t, filepath.Join(logDir, "testlog-2.log")) - assert.NoFileExists(t, logFile) - - // Should be a no-op without a new log - rotateLogs(logFile) - assert.FileExists(t, filepath.Join(logDir, "testlog-1.log")) - assert.NoFileExists(t, filepath.Join(logDir, "testlog-2.log")) - assert.NoFileExists(t, logFile) - - for i := 2; i <= LogRotationCount+1; i++ { - require.NoError(t, os.WriteFile(logFile, []byte(strconv.Itoa(i)), 0o644)) - assert.FileExists(t, logFile) - rotateLogs(logFile) - assert.NoFileExists(t, logFile) - for j := 1; j < i; j++ { - assert.FileExists(t, filepath.Join(logDir, "testlog-"+strconv.Itoa(j)+".log")) - } - assert.NoFileExists(t, filepath.Join(logDir, "testlog-"+strconv.Itoa(i+1)+".log")) - } -} diff --git a/ollama/app/lifecycle/logging_windows.go b/ollama/app/lifecycle/logging_windows.go deleted file mode 100755 index 8f20337..0000000 --- a/ollama/app/lifecycle/logging_windows.go +++ /dev/null @@ -1,19 +0,0 @@ -package lifecycle - -import ( - "fmt" - "log/slog" - "os/exec" - "syscall" -) - -func ShowLogs() { - cmd_path := "c:\\Windows\\system32\\cmd.exe" - slog.Debug(fmt.Sprintf("viewing logs with start %s", AppDataDir)) - cmd := exec.Command(cmd_path, "/c", "start", AppDataDir) - cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: false, CreationFlags: 0x08000000} - err := cmd.Start() - if err != nil { - slog.Error(fmt.Sprintf("Failed to open log dir: %s", err)) - } -} diff --git a/ollama/app/lifecycle/paths.go b/ollama/app/lifecycle/paths.go deleted file mode 100755 index 4d9f4c5..0000000 --- a/ollama/app/lifecycle/paths.go +++ /dev/null @@ -1,79 +0,0 @@ -package lifecycle - -import ( - "errors" - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - "strings" -) - -var ( - AppName = "ollama app" - CLIName = "ollama" - AppDir = "/opt/Ollama" - AppDataDir = "/opt/Ollama" - // TODO - should there be a distinct log dir? - UpdateStageDir = "/tmp" - AppLogFile = "/tmp/ollama_app.log" - ServerLogFile = "/tmp/ollama.log" - UpgradeLogFile = "/tmp/ollama_update.log" - Installer = "OllamaSetup.exe" - LogRotationCount = 5 -) - -func init() { - if runtime.GOOS == "windows" { - AppName += ".exe" - CLIName += ".exe" - // Logs, configs, downloads go to LOCALAPPDATA - localAppData := os.Getenv("LOCALAPPDATA") - AppDataDir = filepath.Join(localAppData, "Ollama") - UpdateStageDir = filepath.Join(AppDataDir, "updates") - AppLogFile = filepath.Join(AppDataDir, "app.log") - ServerLogFile = filepath.Join(AppDataDir, "server.log") - UpgradeLogFile = filepath.Join(AppDataDir, "upgrade.log") - - // Executables are stored in APPDATA - AppDir = filepath.Join(localAppData, "Programs", "Ollama") - - // Make sure we have PATH set correctly for any spawned children - paths := strings.Split(os.Getenv("PATH"), ";") - // Start with whatever we find in the PATH/LD_LIBRARY_PATH - found := false - for _, path := range paths { - d, err := filepath.Abs(path) - if err != nil { - continue - } - if strings.EqualFold(AppDir, d) { - found = true - } - } - if !found { - paths = append(paths, AppDir) - - pathVal := strings.Join(paths, ";") - slog.Debug("setting PATH=" + pathVal) - err := os.Setenv("PATH", pathVal) - if err != nil { - slog.Error(fmt.Sprintf("failed to update PATH: %s", err)) - } - } - - // Make sure our logging dir exists - _, err := os.Stat(AppDataDir) - if errors.Is(err, os.ErrNotExist) { - if err := os.MkdirAll(AppDataDir, 0o755); err != nil { - slog.Error(fmt.Sprintf("create ollama dir %s: %v", AppDataDir, err)) - } - } - } else if runtime.GOOS == "darwin" { - // TODO - AppName += ".app" - // } else if runtime.GOOS == "linux" { - // TODO - } -} diff --git a/ollama/app/lifecycle/server.go b/ollama/app/lifecycle/server.go deleted file mode 100755 index 3795739..0000000 --- a/ollama/app/lifecycle/server.go +++ /dev/null @@ -1,180 +0,0 @@ -package lifecycle - -import ( - "context" - "errors" - "fmt" - "io" - "log/slog" - "os" - "os/exec" - "path/filepath" - "time" - - "github.com/ollama/ollama/api" -) - -func getCLIFullPath(command string) string { - var cmdPath string - appExe, err := os.Executable() - if err == nil { - cmdPath = filepath.Join(filepath.Dir(appExe), command) - _, err := os.Stat(cmdPath) - if err == nil { - return cmdPath - } - } - cmdPath, err = exec.LookPath(command) - if err == nil { - _, err := os.Stat(cmdPath) - if err == nil { - return cmdPath - } - } - pwd, err := os.Getwd() - if err == nil { - cmdPath = filepath.Join(pwd, command) - _, err = os.Stat(cmdPath) - if err == nil { - return cmdPath - } - } - - return command -} - -func start(ctx context.Context, command string) (*exec.Cmd, error) { - cmd := getCmd(ctx, getCLIFullPath(command)) - stdout, err := cmd.StdoutPipe() - if err != nil { - return nil, fmt.Errorf("failed to spawn server stdout pipe: %w", err) - } - stderr, err := cmd.StderrPipe() - if err != nil { - return nil, fmt.Errorf("failed to spawn server stderr pipe: %w", err) - } - - rotateLogs(ServerLogFile) - logFile, err := os.OpenFile(ServerLogFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o755) - if err != nil { - return nil, fmt.Errorf("failed to create server log: %w", err) - } - - logDir := filepath.Dir(ServerLogFile) - _, err = os.Stat(logDir) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return nil, fmt.Errorf("stat ollama server log dir %s: %v", logDir, err) - } - - if err := os.MkdirAll(logDir, 0o755); err != nil { - return nil, fmt.Errorf("create ollama server log dir %s: %v", logDir, err) - } - } - - go func() { - defer logFile.Close() - io.Copy(logFile, stdout) //nolint:errcheck - }() - go func() { - defer logFile.Close() - io.Copy(logFile, stderr) //nolint:errcheck - }() - - // Re-wire context done behavior to attempt a graceful shutdown of the server - cmd.Cancel = func() error { - if cmd.Process != nil { - err := terminate(cmd) - if err != nil { - slog.Warn("error trying to gracefully terminate server", "err", err) - return cmd.Process.Kill() - } - - tick := time.NewTicker(10 * time.Millisecond) - defer tick.Stop() - - for { - select { - case <-tick.C: - exited, err := isProcessExited(cmd.Process.Pid) - if err != nil { - return err - } - - if exited { - return nil - } - case <-time.After(5 * time.Second): - slog.Warn("graceful server shutdown timeout, killing", "pid", cmd.Process.Pid) - return cmd.Process.Kill() - } - } - } - return nil - } - - // run the command and wait for it to finish - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("failed to start server %w", err) - } - if cmd.Process != nil { - slog.Info(fmt.Sprintf("started ollama server with pid %d", cmd.Process.Pid)) - } - slog.Info(fmt.Sprintf("ollama server logs %s", ServerLogFile)) - - return cmd, nil -} - -func SpawnServer(ctx context.Context, command string) (chan int, error) { - done := make(chan int) - - go func() { - // Keep the server running unless we're shuttind down the app - crashCount := 0 - for { - slog.Info("starting server...") - cmd, err := start(ctx, command) - if err != nil { - crashCount++ - slog.Error(fmt.Sprintf("failed to start server %s", err)) - time.Sleep(500 * time.Millisecond * time.Duration(crashCount)) - continue - } - - cmd.Wait() //nolint:errcheck - var code int - if cmd.ProcessState != nil { - code = cmd.ProcessState.ExitCode() - } - - select { - case <-ctx.Done(): - slog.Info(fmt.Sprintf("server shutdown with exit code %d", code)) - done <- code - return - default: - crashCount++ - slog.Warn(fmt.Sprintf("server crash %d - exit code %d - respawning", crashCount, code)) - time.Sleep(500 * time.Millisecond * time.Duration(crashCount)) - break - } - } - }() - - return done, nil -} - -func IsServerRunning(ctx context.Context) bool { - client, err := api.ClientFromEnvironment() - if err != nil { - slog.Info("unable to connect to server") - return false - } - err = client.Heartbeat(ctx) - if err != nil { - slog.Debug(fmt.Sprintf("heartbeat from server: %s", err)) - slog.Info("unable to connect to server") - return false - } - return true -} diff --git a/ollama/app/lifecycle/server_unix.go b/ollama/app/lifecycle/server_unix.go deleted file mode 100755 index 7057391..0000000 --- a/ollama/app/lifecycle/server_unix.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build !windows - -package lifecycle - -import ( - "context" - "errors" - "fmt" - "os" - "os/exec" - "syscall" -) - -func getCmd(ctx context.Context, cmd string) *exec.Cmd { - return exec.CommandContext(ctx, cmd, "serve") -} - -func terminate(cmd *exec.Cmd) error { - return cmd.Process.Signal(os.Interrupt) -} - -func isProcessExited(pid int) (bool, error) { - proc, err := os.FindProcess(pid) - if err != nil { - return false, fmt.Errorf("failed to find process: %v", err) - } - - err = proc.Signal(syscall.Signal(0)) - if err != nil { - if errors.Is(err, os.ErrProcessDone) || errors.Is(err, syscall.ESRCH) { - return true, nil - } - - return false, fmt.Errorf("error signaling process: %v", err) - } - - return false, nil -} diff --git a/ollama/app/lifecycle/server_windows.go b/ollama/app/lifecycle/server_windows.go deleted file mode 100755 index 5f9fe12..0000000 --- a/ollama/app/lifecycle/server_windows.go +++ /dev/null @@ -1,91 +0,0 @@ -package lifecycle - -import ( - "context" - "fmt" - "os/exec" - "syscall" - - "golang.org/x/sys/windows" -) - -func getCmd(ctx context.Context, exePath string) *exec.Cmd { - cmd := exec.CommandContext(ctx, exePath, "serve") - cmd.SysProcAttr = &syscall.SysProcAttr{ - HideWindow: true, - CreationFlags: windows.CREATE_NEW_PROCESS_GROUP, - } - - return cmd -} - -func terminate(cmd *exec.Cmd) error { - dll, err := windows.LoadDLL("kernel32.dll") - if err != nil { - return err - } - //nolint:errcheck - defer dll.Release() - - pid := cmd.Process.Pid - - f, err := dll.FindProc("AttachConsole") - if err != nil { - return err - } - - r1, _, err := f.Call(uintptr(pid)) - if r1 == 0 && err != syscall.ERROR_ACCESS_DENIED { - return err - } - - f, err = dll.FindProc("SetConsoleCtrlHandler") - if err != nil { - return err - } - - r1, _, err = f.Call(0, 1) - if r1 == 0 { - return err - } - - f, err = dll.FindProc("GenerateConsoleCtrlEvent") - if err != nil { - return err - } - - r1, _, err = f.Call(windows.CTRL_BREAK_EVENT, uintptr(pid)) - if r1 == 0 { - return err - } - - r1, _, err = f.Call(windows.CTRL_C_EVENT, uintptr(pid)) - if r1 == 0 { - return err - } - - return nil -} - -const STILL_ACTIVE = 259 - -func isProcessExited(pid int) (bool, error) { - hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid)) - if err != nil { - return false, fmt.Errorf("failed to open process: %v", err) - } - //nolint:errcheck - defer windows.CloseHandle(hProcess) - - var exitCode uint32 - err = windows.GetExitCodeProcess(hProcess, &exitCode) - if err != nil { - return false, fmt.Errorf("failed to get exit code: %v", err) - } - - if exitCode == STILL_ACTIVE { - return false, nil - } - - return true, nil -} diff --git a/ollama/app/lifecycle/updater.go b/ollama/app/lifecycle/updater.go deleted file mode 100755 index 4d3c7d8..0000000 --- a/ollama/app/lifecycle/updater.go +++ /dev/null @@ -1,229 +0,0 @@ -package lifecycle - -import ( - "context" - "crypto/rand" - "encoding/json" - "errors" - "fmt" - "io" - "log/slog" - "mime" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "runtime" - "strconv" - "strings" - "time" - - "github.com/ollama/ollama/auth" - "github.com/ollama/ollama/version" -) - -var ( - UpdateCheckURLBase = "https://ollama.com/api/update" - UpdateDownloaded = false - UpdateCheckInterval = 60 * 60 * time.Second -) - -// TODO - maybe move up to the API package? -type UpdateResponse struct { - UpdateURL string `json:"url"` - UpdateVersion string `json:"version"` -} - -func IsNewReleaseAvailable(ctx context.Context) (bool, UpdateResponse) { - var updateResp UpdateResponse - - requestURL, err := url.Parse(UpdateCheckURLBase) - if err != nil { - return false, updateResp - } - - query := requestURL.Query() - query.Add("os", runtime.GOOS) - query.Add("arch", runtime.GOARCH) - query.Add("version", version.Version) - query.Add("ts", strconv.FormatInt(time.Now().Unix(), 10)) - - nonce, err := auth.NewNonce(rand.Reader, 16) - if err != nil { - return false, updateResp - } - - query.Add("nonce", nonce) - requestURL.RawQuery = query.Encode() - - data := []byte(fmt.Sprintf("%s,%s", http.MethodGet, requestURL.RequestURI())) - signature, err := auth.Sign(ctx, data) - if err != nil { - return false, updateResp - } - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL.String(), nil) - if err != nil { - slog.Warn(fmt.Sprintf("failed to check for update: %s", err)) - return false, updateResp - } - req.Header.Set("Authorization", signature) - req.Header.Set("User-Agent", fmt.Sprintf("ollama/%s (%s %s) Go/%s", version.Version, runtime.GOARCH, runtime.GOOS, runtime.Version())) - - slog.Debug("checking for available update", "requestURL", requestURL) - resp, err := http.DefaultClient.Do(req) - if err != nil { - slog.Warn(fmt.Sprintf("failed to check for update: %s", err)) - return false, updateResp - } - defer resp.Body.Close() - - if resp.StatusCode == http.StatusNoContent { - slog.Debug("check update response 204 (current version is up to date)") - return false, updateResp - } - body, err := io.ReadAll(resp.Body) - if err != nil { - slog.Warn(fmt.Sprintf("failed to read body response: %s", err)) - } - - if resp.StatusCode != http.StatusOK { - slog.Info(fmt.Sprintf("check update error %d - %.96s", resp.StatusCode, string(body))) - return false, updateResp - } - err = json.Unmarshal(body, &updateResp) - if err != nil { - slog.Warn(fmt.Sprintf("malformed response checking for update: %s", err)) - return false, updateResp - } - // Extract the version string from the URL in the github release artifact path - updateResp.UpdateVersion = path.Base(path.Dir(updateResp.UpdateURL)) - - slog.Info("New update available at " + updateResp.UpdateURL) - return true, updateResp -} - -func DownloadNewRelease(ctx context.Context, updateResp UpdateResponse) error { - // Do a head first to check etag info - req, err := http.NewRequestWithContext(ctx, http.MethodHead, updateResp.UpdateURL, nil) - if err != nil { - return err - } - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("error checking update: %w", err) - } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("unexpected status attempting to download update %d", resp.StatusCode) - } - resp.Body.Close() - etag := strings.Trim(resp.Header.Get("etag"), "\"") - if etag == "" { - slog.Debug("no etag detected, falling back to filename based dedup") - etag = "_" - } - filename := Installer - _, params, err := mime.ParseMediaType(resp.Header.Get("content-disposition")) - if err == nil { - filename = params["filename"] - } - - stageFilename := filepath.Join(UpdateStageDir, etag, filename) - - // Check to see if we already have it downloaded - _, err = os.Stat(stageFilename) - if err == nil { - slog.Info("update already downloaded") - return nil - } - - cleanupOldDownloads() - - req.Method = http.MethodGet - resp, err = http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("error checking update: %w", err) - } - defer resp.Body.Close() - etag = strings.Trim(resp.Header.Get("etag"), "\"") - if etag == "" { - slog.Debug("no etag detected, falling back to filename based dedup") // TODO probably can get rid of this redundant log - etag = "_" - } - - stageFilename = filepath.Join(UpdateStageDir, etag, filename) - - _, err = os.Stat(filepath.Dir(stageFilename)) - if errors.Is(err, os.ErrNotExist) { - if err := os.MkdirAll(filepath.Dir(stageFilename), 0o755); err != nil { - return fmt.Errorf("create ollama dir %s: %v", filepath.Dir(stageFilename), err) - } - } - - payload, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed to read body response: %w", err) - } - fp, err := os.OpenFile(stageFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) - if err != nil { - return fmt.Errorf("write payload %s: %w", stageFilename, err) - } - defer fp.Close() - if n, err := fp.Write(payload); err != nil || n != len(payload) { - return fmt.Errorf("write payload %s: %d vs %d -- %w", stageFilename, n, len(payload), err) - } - slog.Info("new update downloaded " + stageFilename) - - UpdateDownloaded = true - return nil -} - -func cleanupOldDownloads() { - files, err := os.ReadDir(UpdateStageDir) - if err != nil && errors.Is(err, os.ErrNotExist) { - // Expected behavior on first run - return - } else if err != nil { - slog.Warn(fmt.Sprintf("failed to list stage dir: %s", err)) - return - } - for _, file := range files { - fullname := filepath.Join(UpdateStageDir, file.Name()) - slog.Debug("cleaning up old download: " + fullname) - err = os.RemoveAll(fullname) - if err != nil { - slog.Warn(fmt.Sprintf("failed to cleanup stale update download %s", err)) - } - } -} - -func StartBackgroundUpdaterChecker(ctx context.Context, cb func(string) error) { - go func() { - // Don't blast an update message immediately after startup - // time.Sleep(30 * time.Second) - time.Sleep(3 * time.Second) - - for { - available, resp := IsNewReleaseAvailable(ctx) - if available { - err := DownloadNewRelease(ctx, resp) - if err != nil { - slog.Error(fmt.Sprintf("failed to download new release: %s", err)) - } - err = cb(resp.UpdateVersion) - if err != nil { - slog.Warn(fmt.Sprintf("failed to register update available with tray: %s", err)) - } - } - select { - case <-ctx.Done(): - slog.Debug("stopping background update checker") - return - default: - time.Sleep(UpdateCheckInterval) - } - } - }() -} diff --git a/ollama/app/lifecycle/updater_nonwindows.go b/ollama/app/lifecycle/updater_nonwindows.go deleted file mode 100755 index 1d2dda8..0000000 --- a/ollama/app/lifecycle/updater_nonwindows.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !windows - -package lifecycle - -import ( - "context" - "errors" -) - -func DoUpgrade(cancel context.CancelFunc, done chan int) error { - return errors.New("not implemented") -} diff --git a/ollama/app/lifecycle/updater_windows.go b/ollama/app/lifecycle/updater_windows.go deleted file mode 100755 index 1d3830d..0000000 --- a/ollama/app/lifecycle/updater_windows.go +++ /dev/null @@ -1,78 +0,0 @@ -package lifecycle - -import ( - "context" - "errors" - "fmt" - "log/slog" - "os" - "os/exec" - "path/filepath" -) - -func DoUpgrade(cancel context.CancelFunc, done chan int) error { - files, err := filepath.Glob(filepath.Join(UpdateStageDir, "*", "*.exe")) // TODO generalize for multiplatform - if err != nil { - return fmt.Errorf("failed to lookup downloads: %s", err) - } - if len(files) == 0 { - return errors.New("no update downloads found") - } else if len(files) > 1 { - // Shouldn't happen - slog.Warn(fmt.Sprintf("multiple downloads found, using first one %v", files)) - } - installerExe := files[0] - - slog.Info("starting upgrade with " + installerExe) - slog.Info("upgrade log file " + UpgradeLogFile) - - // When running in debug mode, we'll be "verbose" and let the installer pop up and prompt - installArgs := []string{ - "/CLOSEAPPLICATIONS", // Quit the tray app if it's still running - "/LOG=" + filepath.Base(UpgradeLogFile), // Only relative seems reliable, so set pwd - "/FORCECLOSEAPPLICATIONS", // Force close the tray app - might be needed - } - // make the upgrade as quiet as possible (no GUI, no prompts) - installArgs = append(installArgs, - "/SP", // Skip the "This will install... Do you wish to continue" prompt - "/SUPPRESSMSGBOXES", - "/SILENT", - "/VERYSILENT", - ) - - // Safeguard in case we have requests in flight that need to drain... - slog.Info("Waiting for server to shutdown") - cancel() - if done != nil { - <-done - } else { - // Shouldn't happen - slog.Warn("done chan was nil, not actually waiting") - } - - slog.Debug(fmt.Sprintf("starting installer: %s %v", installerExe, installArgs)) - os.Chdir(filepath.Dir(UpgradeLogFile)) //nolint:errcheck - cmd := exec.Command(installerExe, installArgs...) - - if err := cmd.Start(); err != nil { - return fmt.Errorf("unable to start ollama app %w", err) - } - - if cmd.Process != nil { - err = cmd.Process.Release() - if err != nil { - slog.Error(fmt.Sprintf("failed to release server process: %s", err)) - } - } else { - // TODO - some details about why it didn't start, or is this a pedantic error case? - return errors.New("installer process did not start") - } - - // TODO should we linger for a moment and check to make sure it's actually running by checking the pid? - - slog.Info("Installer started in background, exiting") - - os.Exit(0) - // Not reached - return nil -} diff --git a/ollama/app/main.go b/ollama/app/main.go deleted file mode 100755 index db82979..0000000 --- a/ollama/app/main.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -// Compile with the following to get rid of the cmd pop up on windows -// go build -ldflags="-H windowsgui" . - -import ( - "github.com/ollama/ollama/app/lifecycle" -) - -func main() { - lifecycle.Run() -} diff --git a/ollama/app/ollama.iss b/ollama/app/ollama.iss deleted file mode 100755 index dc6178f..0000000 --- a/ollama/app/ollama.iss +++ /dev/null @@ -1,165 +0,0 @@ -; Inno Setup Installer for Ollama -; -; To build the installer use the build script invoked from the top of the source tree -; -; powershell -ExecutionPolicy Bypass -File .\scripts\build_windows.ps - - -#define MyAppName "Ollama" -#if GetEnv("PKG_VERSION") != "" - #define MyAppVersion GetEnv("PKG_VERSION") -#else - #define MyAppVersion "0.0.0" -#endif -#define MyAppPublisher "Ollama" -#define MyAppURL "https://ollama.com/" -#define MyAppExeName "ollama app.exe" -#define MyIcon ".\assets\app.ico" - -[Setup] -; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. -; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) -AppId={{44E83376-CE68-45EB-8FC1-393500EB558C} -AppName={#MyAppName} -AppVersion={#MyAppVersion} -VersionInfoVersion={#MyAppVersion} -;AppVerName={#MyAppName} {#MyAppVersion} -AppPublisher={#MyAppPublisher} -AppPublisherURL={#MyAppURL} -AppSupportURL={#MyAppURL} -AppUpdatesURL={#MyAppURL} -ArchitecturesAllowed=x64 arm64 -ArchitecturesInstallIn64BitMode=x64 arm64 -DefaultDirName={localappdata}\Programs\{#MyAppName} -DefaultGroupName={#MyAppName} -DisableProgramGroupPage=yes -PrivilegesRequired=lowest -OutputBaseFilename="OllamaSetup" -SetupIconFile={#MyIcon} -UninstallDisplayIcon={uninstallexe} -Compression=lzma2 -SolidCompression=no -WizardStyle=modern -ChangesEnvironment=yes -OutputDir=..\dist\ - -; Disable logging once everything's battle tested -; Filename will be %TEMP%\Setup Log*.txt -SetupLogging=yes -CloseApplications=yes -RestartApplications=no - -; https://jrsoftware.org/ishelp/index.php?topic=setup_wizardimagefile -WizardSmallImageFile=.\assets\setup.bmp - -; TODO verifty actual min windows version... -; OG Win 10 -MinVersion=10.0.10240 - -; First release that supports WinRT UI Composition for win32 apps -; MinVersion=10.0.17134 -; First release with XAML Islands - possible UI path forward -; MinVersion=10.0.18362 - -; quiet... -DisableDirPage=yes -DisableFinishedPage=yes -DisableReadyMemo=yes -DisableReadyPage=yes -DisableStartupPrompt=yes -DisableWelcomePage=yes - -; TODO - percentage can't be set less than 100, so how to make it shorter? -; WizardSizePercent=100,80 - -#if GetEnv("KEY_CONTAINER") -SignTool=MySignTool -SignedUninstaller=yes -#endif - -SetupMutex=OllamaSetupMutex - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" - -[LangOptions] -DialogFontSize=12 - -[Files] -Source: ".\app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ; Flags: ignoreversion 64bit -Source: "..\ollama.exe"; DestDir: "{app}"; Flags: ignoreversion 64bit -Source: "..\dist\windows-{#ARCH}\ollama_runners\*"; DestDir: "{app}\ollama_runners"; Flags: ignoreversion 64bit recursesubdirs -Source: "..\dist\ollama_welcome.ps1"; DestDir: "{app}"; Flags: ignoreversion -Source: ".\assets\app.ico"; DestDir: "{app}"; Flags: ignoreversion -#if DirExists("..\dist\windows-amd64\cuda") - Source: "..\dist\windows-amd64\cuda\*"; DestDir: "{app}\cuda\"; Flags: ignoreversion recursesubdirs -#endif -#if DirExists("..\dist\windows-amd64\oneapi") - Source: "..\dist\windows-amd64\oneapi\*"; DestDir: "{app}\oneapi\"; Flags: ignoreversion recursesubdirs -#endif -#if DirExists("..\dist\windows-amd64\rocm") - Source: "..\dist\windows-amd64\rocm\*"; DestDir: "{app}\rocm\"; Flags: ignoreversion recursesubdirs -#endif - - -[Icons] -Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico" -Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico" -Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico" - -[Run] -Filename: "{cmd}"; Parameters: "/C set PATH={app};%PATH% & ""{app}\{#MyAppExeName}"""; Flags: postinstall nowait runhidden - -[UninstallRun] -; Filename: "{cmd}"; Parameters: "/C ""taskkill /im ''{#MyAppExeName}'' /f /t"; Flags: runhidden -; Filename: "{cmd}"; Parameters: "/C ""taskkill /im ollama.exe /f /t"; Flags: runhidden -Filename: "taskkill"; Parameters: "/im ""{#MyAppExeName}"" /f /t"; Flags: runhidden -Filename: "taskkill"; Parameters: "/im ""ollama.exe"" /f /t"; Flags: runhidden -; HACK! need to give the server and app enough time to exit -; TODO - convert this to a Pascal code script so it waits until they're no longer running, then completes -Filename: "{cmd}"; Parameters: "/c timeout 5"; Flags: runhidden - -[UninstallDelete] -Type: filesandordirs; Name: "{%TEMP}\ollama*" -Type: filesandordirs; Name: "{%LOCALAPPDATA}\Ollama" -Type: filesandordirs; Name: "{%LOCALAPPDATA}\Programs\Ollama" -Type: filesandordirs; Name: "{%USERPROFILE}\.ollama\models" -Type: filesandordirs; Name: "{%USERPROFILE}\.ollama\history" -; NOTE: if the user has a custom OLLAMA_MODELS it will be preserved - -[InstallDelete] -Type: filesandordirs; Name: "{%TEMP}\ollama*" -Type: filesandordirs; Name: "{%LOCALAPPDATA}\Programs\Ollama" - -[Messages] -WizardReady=Ollama Windows Preview -ReadyLabel1=%nLet's get you up and running with your own large language models. -SetupAppRunningError=Another Ollama installer is running.%n%nPlease cancel or finish the other installer, then click OK to continue with this install, or Cancel to exit. - - -;FinishedHeadingLabel=Run your first model -;FinishedLabel=%nRun this command in a PowerShell or cmd terminal.%n%n%n ollama run llama3.1 -;ClickFinish=%n - -[Registry] -Root: HKCU; Subkey: "Environment"; \ - ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; \ - Check: NeedsAddPath('{app}') - -[Code] - -function NeedsAddPath(Param: string): boolean; -var - OrigPath: string; -begin - if not RegQueryStringValue(HKEY_CURRENT_USER, - 'Environment', - 'Path', OrigPath) - then begin - Result := True; - exit; - end; - { look for the path with leading and trailing semicolon } - { Pos() returns 0 if not found } - Result := Pos(';' + ExpandConstant(Param) + ';', ';' + OrigPath + ';') = 0; -end; diff --git a/ollama/app/ollama.rc b/ollama/app/ollama.rc deleted file mode 100755 index acd8449..0000000 --- a/ollama/app/ollama.rc +++ /dev/null @@ -1,29 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "Ollama" - VALUE "InternalName", "Ollama" - VALUE "OriginalFilename", "ollama app.exe" - VALUE "ProductName", "Ollama" - END - END - - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/ollama/app/ollama_welcome.ps1 b/ollama/app/ollama_welcome.ps1 deleted file mode 100755 index 46777a3..0000000 --- a/ollama/app/ollama_welcome.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# TODO - consider ANSI colors and maybe ASCII art... -write-host "" -write-host "Welcome to Ollama!" -write-host "" -write-host "Run your first model:" -write-host "" -write-host "`tollama run llama3.1" -write-host "" \ No newline at end of file diff --git a/ollama/app/store/store.go b/ollama/app/store/store.go deleted file mode 100755 index b743e8a..0000000 --- a/ollama/app/store/store.go +++ /dev/null @@ -1,97 +0,0 @@ -package store - -import ( - "encoding/json" - "errors" - "fmt" - "log/slog" - "os" - "path/filepath" - "sync" - - "github.com/google/uuid" -) - -type Store struct { - ID string `json:"id"` - FirstTimeRun bool `json:"first-time-run"` -} - -var ( - lock sync.Mutex - store Store -) - -func GetID() string { - lock.Lock() - defer lock.Unlock() - if store.ID == "" { - initStore() - } - return store.ID -} - -func GetFirstTimeRun() bool { - lock.Lock() - defer lock.Unlock() - if store.ID == "" { - initStore() - } - return store.FirstTimeRun -} - -func SetFirstTimeRun(val bool) { - lock.Lock() - defer lock.Unlock() - if store.FirstTimeRun == val { - return - } - store.FirstTimeRun = val - writeStore(getStorePath()) -} - -// lock must be held -func initStore() { - storeFile, err := os.Open(getStorePath()) - if err == nil { - defer storeFile.Close() - err = json.NewDecoder(storeFile).Decode(&store) - if err == nil { - slog.Debug(fmt.Sprintf("loaded existing store %s - ID: %s", getStorePath(), store.ID)) - return - } - } else if !errors.Is(err, os.ErrNotExist) { - slog.Debug(fmt.Sprintf("unexpected error searching for store: %s", err)) - } - slog.Debug("initializing new store") - store.ID = uuid.New().String() - writeStore(getStorePath()) -} - -func writeStore(storeFilename string) { - ollamaDir := filepath.Dir(storeFilename) - _, err := os.Stat(ollamaDir) - if errors.Is(err, os.ErrNotExist) { - if err := os.MkdirAll(ollamaDir, 0o755); err != nil { - slog.Error(fmt.Sprintf("create ollama dir %s: %v", ollamaDir, err)) - return - } - } - payload, err := json.Marshal(store) - if err != nil { - slog.Error(fmt.Sprintf("failed to marshal store: %s", err)) - return - } - fp, err := os.OpenFile(storeFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) - if err != nil { - slog.Error(fmt.Sprintf("write store payload %s: %v", storeFilename, err)) - return - } - defer fp.Close() - if n, err := fp.Write(payload); err != nil || n != len(payload) { - slog.Error(fmt.Sprintf("write store payload %s: %d vs %d -- %v", storeFilename, n, len(payload), err)) - return - } - slog.Debug("Store contents: " + string(payload)) - slog.Info(fmt.Sprintf("wrote store: %s", storeFilename)) -} diff --git a/ollama/app/store/store_darwin.go b/ollama/app/store/store_darwin.go deleted file mode 100755 index e53d852..0000000 --- a/ollama/app/store/store_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -package store - -import ( - "os" - "path/filepath" -) - -func getStorePath() string { - // TODO - system wide location? - - home := os.Getenv("HOME") - return filepath.Join(home, "Library", "Application Support", "Ollama", "config.json") -} diff --git a/ollama/app/store/store_linux.go b/ollama/app/store/store_linux.go deleted file mode 100755 index 3aac9b0..0000000 --- a/ollama/app/store/store_linux.go +++ /dev/null @@ -1,16 +0,0 @@ -package store - -import ( - "os" - "path/filepath" -) - -func getStorePath() string { - if os.Geteuid() == 0 { - // TODO where should we store this on linux for system-wide operation? - return "/etc/ollama/config.json" - } - - home := os.Getenv("HOME") - return filepath.Join(home, ".ollama", "config.json") -} diff --git a/ollama/app/store/store_windows.go b/ollama/app/store/store_windows.go deleted file mode 100755 index ba06b82..0000000 --- a/ollama/app/store/store_windows.go +++ /dev/null @@ -1,11 +0,0 @@ -package store - -import ( - "os" - "path/filepath" -) - -func getStorePath() string { - localAppData := os.Getenv("LOCALAPPDATA") - return filepath.Join(localAppData, "Ollama", "config.json") -} diff --git a/ollama/app/tray/commontray/types.go b/ollama/app/tray/commontray/types.go deleted file mode 100755 index ed633dc..0000000 --- a/ollama/app/tray/commontray/types.go +++ /dev/null @@ -1,24 +0,0 @@ -package commontray - -var ( - Title = "Ollama" - ToolTip = "Ollama" - - UpdateIconName = "tray_upgrade" - IconName = "tray" -) - -type Callbacks struct { - Quit chan struct{} - Update chan struct{} - DoFirstUse chan struct{} - ShowLogs chan struct{} -} - -type OllamaTray interface { - GetCallbacks() Callbacks - Run() - UpdateAvailable(ver string) error - DisplayFirstUseNotification() error - Quit() -} diff --git a/ollama/app/tray/tray.go b/ollama/app/tray/tray.go deleted file mode 100755 index dfa6343..0000000 --- a/ollama/app/tray/tray.go +++ /dev/null @@ -1,28 +0,0 @@ -package tray - -import ( - "fmt" - "runtime" - - "github.com/ollama/ollama/app/assets" - "github.com/ollama/ollama/app/tray/commontray" -) - -func NewTray() (commontray.OllamaTray, error) { - extension := ".png" - if runtime.GOOS == "windows" { - extension = ".ico" - } - iconName := commontray.UpdateIconName + extension - updateIcon, err := assets.GetIcon(iconName) - if err != nil { - return nil, fmt.Errorf("failed to load icon %s: %w", iconName, err) - } - iconName = commontray.IconName + extension - icon, err := assets.GetIcon(iconName) - if err != nil { - return nil, fmt.Errorf("failed to load icon %s: %w", iconName, err) - } - - return InitPlatformTray(icon, updateIcon) -} diff --git a/ollama/app/tray/tray_nonwindows.go b/ollama/app/tray/tray_nonwindows.go deleted file mode 100755 index a03d233..0000000 --- a/ollama/app/tray/tray_nonwindows.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows - -package tray - -import ( - "errors" - - "github.com/ollama/ollama/app/tray/commontray" -) - -func InitPlatformTray(icon, updateIcon []byte) (commontray.OllamaTray, error) { - return nil, errors.New("not implemented") -} diff --git a/ollama/app/tray/tray_windows.go b/ollama/app/tray/tray_windows.go deleted file mode 100755 index 086fc79..0000000 --- a/ollama/app/tray/tray_windows.go +++ /dev/null @@ -1,10 +0,0 @@ -package tray - -import ( - "github.com/ollama/ollama/app/tray/commontray" - "github.com/ollama/ollama/app/tray/wintray" -) - -func InitPlatformTray(icon, updateIcon []byte) (commontray.OllamaTray, error) { - return wintray.InitTray(icon, updateIcon) -} diff --git a/ollama/app/tray/wintray/eventloop.go b/ollama/app/tray/wintray/eventloop.go deleted file mode 100755 index 157828a..0000000 --- a/ollama/app/tray/wintray/eventloop.go +++ /dev/null @@ -1,181 +0,0 @@ -//go:build windows - -package wintray - -import ( - "fmt" - "log/slog" - "sync" - "unsafe" - - "golang.org/x/sys/windows" -) - -var quitOnce sync.Once - -func (t *winTray) Run() { - nativeLoop() -} - -func nativeLoop() { - // Main message pump. - slog.Debug("starting event handling loop") - m := &struct { - WindowHandle windows.Handle - Message uint32 - Wparam uintptr - Lparam uintptr - Time uint32 - Pt point - LPrivate uint32 - }{} - for { - ret, _, err := pGetMessage.Call(uintptr(unsafe.Pointer(m)), 0, 0, 0) - - // If the function retrieves a message other than WM_QUIT, the return value is nonzero. - // If the function retrieves the WM_QUIT message, the return value is zero. - // If there is an error, the return value is -1 - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx - switch int32(ret) { - case -1: - slog.Error(fmt.Sprintf("get message failure: %v", err)) - return - case 0: - return - default: - pTranslateMessage.Call(uintptr(unsafe.Pointer(m))) //nolint:errcheck - pDispatchMessage.Call(uintptr(unsafe.Pointer(m))) //nolint:errcheck - } - } -} - -// WindowProc callback function that processes messages sent to a window. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx -func (t *winTray) wndProc(hWnd windows.Handle, message uint32, wParam, lParam uintptr) (lResult uintptr) { - const ( - WM_RBUTTONUP = 0x0205 - WM_LBUTTONUP = 0x0202 - WM_COMMAND = 0x0111 - WM_ENDSESSION = 0x0016 - WM_CLOSE = 0x0010 - WM_DESTROY = 0x0002 - WM_MOUSEMOVE = 0x0200 - WM_LBUTTONDOWN = 0x0201 - ) - switch message { - case WM_COMMAND: - menuItemId := int32(wParam) - // https://docs.microsoft.com/en-us/windows/win32/menurc/wm-command#menus - switch menuItemId { - case quitMenuID: - select { - case t.callbacks.Quit <- struct{}{}: - // should not happen but in case not listening - default: - slog.Error("no listener on Quit") - } - case updateMenuID: - select { - case t.callbacks.Update <- struct{}{}: - // should not happen but in case not listening - default: - slog.Error("no listener on Update") - } - case diagLogsMenuID: - select { - case t.callbacks.ShowLogs <- struct{}{}: - // should not happen but in case not listening - default: - slog.Error("no listener on ShowLogs") - } - default: - slog.Debug(fmt.Sprintf("Unexpected menu item id: %d", menuItemId)) - } - case WM_CLOSE: - boolRet, _, err := pDestroyWindow.Call(uintptr(t.window)) - if boolRet == 0 { - slog.Error(fmt.Sprintf("failed to destroy window: %s", err)) - } - err = t.wcex.unregister() - if err != nil { - slog.Error(fmt.Sprintf("failed to uregister windo %s", err)) - } - case WM_DESTROY: - // same as WM_ENDSESSION, but throws 0 exit code after all - defer pPostQuitMessage.Call(uintptr(int32(0))) //nolint:errcheck - fallthrough - case WM_ENDSESSION: - t.muNID.Lock() - if t.nid != nil { - err := t.nid.delete() - if err != nil { - slog.Error(fmt.Sprintf("failed to delete nid: %s", err)) - } - } - t.muNID.Unlock() - case t.wmSystrayMessage: - switch lParam { - case WM_MOUSEMOVE, WM_LBUTTONDOWN: - // Ignore these... - case WM_RBUTTONUP, WM_LBUTTONUP: - err := t.showMenu() - if err != nil { - slog.Error(fmt.Sprintf("failed to show menu: %s", err)) - } - case 0x405: // TODO - how is this magic value derived for the notification left click - if t.pendingUpdate { - select { - case t.callbacks.Update <- struct{}{}: - // should not happen but in case not listening - default: - slog.Error("no listener on Update") - } - } else { - select { - case t.callbacks.DoFirstUse <- struct{}{}: - // should not happen but in case not listening - default: - slog.Error("no listener on DoFirstUse") - } - } - case 0x404: // Middle click or close notification - // slog.Debug("doing nothing on close of first time notification") - default: - // 0x402 also seems common - what is it? - slog.Debug(fmt.Sprintf("unmanaged app message, lParm: 0x%x", lParam)) - } - case t.wmTaskbarCreated: // on explorer.exe restarts - t.muNID.Lock() - err := t.nid.add() - if err != nil { - slog.Error(fmt.Sprintf("failed to refresh the taskbar on explorer restart: %s", err)) - } - t.muNID.Unlock() - default: - // Calls the default window procedure to provide default processing for any window messages that an application does not process. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633572(v=vs.85).aspx - lResult, _, _ = pDefWindowProc.Call( - uintptr(hWnd), - uintptr(message), - wParam, - lParam, - ) - } - return -} - -func (t *winTray) Quit() { - quitOnce.Do(quit) -} - -func quit() { - boolRet, _, err := pPostMessage.Call( - uintptr(wt.window), - WM_CLOSE, - 0, - 0, - ) - if boolRet == 0 { - slog.Error(fmt.Sprintf("failed to post close message on shutdown %s", err)) - } -} diff --git a/ollama/app/tray/wintray/menus.go b/ollama/app/tray/wintray/menus.go deleted file mode 100755 index 9cb3b89..0000000 --- a/ollama/app/tray/wintray/menus.go +++ /dev/null @@ -1,71 +0,0 @@ -//go:build windows - -package wintray - -import ( - "fmt" - "log/slog" - "unsafe" - - "golang.org/x/sys/windows" -) - -const ( - updatAvailableMenuID = 1 - updateMenuID = updatAvailableMenuID + 1 - separatorMenuID = updateMenuID + 1 - diagLogsMenuID = separatorMenuID + 1 - diagSeparatorMenuID = diagLogsMenuID + 1 - quitMenuID = diagSeparatorMenuID + 1 -) - -func (t *winTray) initMenus() error { - if err := t.addOrUpdateMenuItem(diagLogsMenuID, 0, diagLogsMenuTitle, false); err != nil { - return fmt.Errorf("unable to create menu entries %w\n", err) - } - if err := t.addSeparatorMenuItem(diagSeparatorMenuID, 0); err != nil { - return fmt.Errorf("unable to create menu entries %w", err) - } - if err := t.addOrUpdateMenuItem(quitMenuID, 0, quitMenuTitle, false); err != nil { - return fmt.Errorf("unable to create menu entries %w\n", err) - } - return nil -} - -func (t *winTray) UpdateAvailable(ver string) error { - if !t.updateNotified { - slog.Debug("updating menu and sending notification for new update") - if err := t.addOrUpdateMenuItem(updatAvailableMenuID, 0, updateAvailableMenuTitle, true); err != nil { - return fmt.Errorf("unable to create menu entries %w", err) - } - if err := t.addOrUpdateMenuItem(updateMenuID, 0, updateMenutTitle, false); err != nil { - return fmt.Errorf("unable to create menu entries %w", err) - } - if err := t.addSeparatorMenuItem(separatorMenuID, 0); err != nil { - return fmt.Errorf("unable to create menu entries %w", err) - } - iconFilePath, err := iconBytesToFilePath(wt.updateIcon) - if err != nil { - return fmt.Errorf("unable to write icon data to temp file: %w", err) - } - if err := wt.setIcon(iconFilePath); err != nil { - return fmt.Errorf("unable to set icon: %w", err) - } - t.updateNotified = true - - t.pendingUpdate = true - // Now pop up the notification - t.muNID.Lock() - defer t.muNID.Unlock() - copy(t.nid.InfoTitle[:], windows.StringToUTF16(updateTitle)) - copy(t.nid.Info[:], windows.StringToUTF16(fmt.Sprintf(updateMessage, ver))) - t.nid.Flags |= NIF_INFO - t.nid.Timeout = 10 - t.nid.Size = uint32(unsafe.Sizeof(*wt.nid)) - err = t.nid.modify() - if err != nil { - return err - } - } - return nil -} diff --git a/ollama/app/tray/wintray/messages.go b/ollama/app/tray/wintray/messages.go deleted file mode 100755 index d364c71..0000000 --- a/ollama/app/tray/wintray/messages.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build windows - -package wintray - -const ( - firstTimeTitle = "Ollama is running" - firstTimeMessage = "Click here to get started" - updateTitle = "Update available" - updateMessage = "Ollama version %s is ready to install" - - quitMenuTitle = "Quit Ollama" - updateAvailableMenuTitle = "An update is available" - updateMenutTitle = "Restart to update" - diagLogsMenuTitle = "View logs" -) diff --git a/ollama/app/tray/wintray/notifyicon.go b/ollama/app/tray/wintray/notifyicon.go deleted file mode 100755 index 4707166..0000000 --- a/ollama/app/tray/wintray/notifyicon.go +++ /dev/null @@ -1,66 +0,0 @@ -//go:build windows - -package wintray - -import ( - "unsafe" - - "golang.org/x/sys/windows" -) - -// Contains information that the system needs to display notifications in the notification area. -// Used by Shell_NotifyIcon. -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159 -type notifyIconData struct { - Size uint32 - Wnd windows.Handle - ID, Flags, CallbackMessage uint32 - Icon windows.Handle - Tip [128]uint16 - State, StateMask uint32 - Info [256]uint16 - // Timeout, Version uint32 - Timeout uint32 - - InfoTitle [64]uint16 - InfoFlags uint32 - GuidItem windows.GUID - BalloonIcon windows.Handle -} - -func (nid *notifyIconData) add() error { - const NIM_ADD = 0x00000000 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_ADD), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) modify() error { - const NIM_MODIFY = 0x00000001 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_MODIFY), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) delete() error { - const NIM_DELETE = 0x00000002 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_DELETE), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} diff --git a/ollama/app/tray/wintray/tray.go b/ollama/app/tray/wintray/tray.go deleted file mode 100755 index ccd087a..0000000 --- a/ollama/app/tray/wintray/tray.go +++ /dev/null @@ -1,482 +0,0 @@ -//go:build windows - -package wintray - -import ( - "crypto/md5" - "encoding/hex" - "fmt" - "log/slog" - "os" - "path/filepath" - "sort" - "sync" - "unsafe" - - "golang.org/x/sys/windows" - - "github.com/ollama/ollama/app/tray/commontray" -) - -// Helpful sources: https://github.com/golang/exp/blob/master/shiny/driver/internal/win32 - -// Contains information about loaded resources -type winTray struct { - instance, - icon, - cursor, - window windows.Handle - - loadedImages map[string]windows.Handle - muLoadedImages sync.RWMutex - - // menus keeps track of the submenus keyed by the menu item ID, plus 0 - // which corresponds to the main popup menu. - menus map[uint32]windows.Handle - muMenus sync.RWMutex - menuOf map[uint32]windows.Handle - muMenuOf sync.RWMutex - // menuItemIcons maintains the bitmap of each menu item (if applies). It's - // needed to show the icon correctly when showing a previously hidden menu - // item again. - // menuItemIcons map[uint32]windows.Handle - // muMenuItemIcons sync.RWMutex - visibleItems map[uint32][]uint32 - muVisibleItems sync.RWMutex - - nid *notifyIconData - muNID sync.RWMutex - wcex *wndClassEx - - wmSystrayMessage, - wmTaskbarCreated uint32 - - pendingUpdate bool - updateNotified bool // Only pop up the notification once - TODO consider daily nag? - // Callbacks - callbacks commontray.Callbacks - normalIcon []byte - updateIcon []byte -} - -var wt winTray - -func (t *winTray) GetCallbacks() commontray.Callbacks { - return t.callbacks -} - -func InitTray(icon, updateIcon []byte) (*winTray, error) { - wt.callbacks.Quit = make(chan struct{}) - wt.callbacks.Update = make(chan struct{}) - wt.callbacks.ShowLogs = make(chan struct{}) - wt.callbacks.DoFirstUse = make(chan struct{}) - wt.normalIcon = icon - wt.updateIcon = updateIcon - if err := wt.initInstance(); err != nil { - return nil, fmt.Errorf("Unable to init instance: %w\n", err) - } - - if err := wt.createMenu(); err != nil { - return nil, fmt.Errorf("Unable to create menu: %w\n", err) - } - - iconFilePath, err := iconBytesToFilePath(wt.normalIcon) - if err != nil { - return nil, fmt.Errorf("Unable to write icon data to temp file: %w", err) - } - if err := wt.setIcon(iconFilePath); err != nil { - return nil, fmt.Errorf("Unable to set icon: %w", err) - } - - return &wt, wt.initMenus() -} - -func (t *winTray) initInstance() error { - const ( - className = "OllamaClass" - windowName = "" - ) - - t.wmSystrayMessage = WM_USER + 1 - t.visibleItems = make(map[uint32][]uint32) - t.menus = make(map[uint32]windows.Handle) - t.menuOf = make(map[uint32]windows.Handle) - - t.loadedImages = make(map[string]windows.Handle) - - taskbarEventNamePtr, _ := windows.UTF16PtrFromString("TaskbarCreated") - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644947 - res, _, err := pRegisterWindowMessage.Call( - uintptr(unsafe.Pointer(taskbarEventNamePtr)), - ) - if res == 0 { // success 0xc000-0xfff - return fmt.Errorf("failed to register window: %w", err) - } - t.wmTaskbarCreated = uint32(res) - - instanceHandle, _, err := pGetModuleHandle.Call(0) - if instanceHandle == 0 { - return err - } - t.instance = windows.Handle(instanceHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648072(v=vs.85).aspx - iconHandle, _, err := pLoadIcon.Call(0, uintptr(IDI_APPLICATION)) - if iconHandle == 0 { - return err - } - t.icon = windows.Handle(iconHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648391(v=vs.85).aspx - cursorHandle, _, err := pLoadCursor.Call(0, uintptr(IDC_ARROW)) - if cursorHandle == 0 { - return err - } - t.cursor = windows.Handle(cursorHandle) - - classNamePtr, err := windows.UTF16PtrFromString(className) - if err != nil { - return err - } - - windowNamePtr, err := windows.UTF16PtrFromString(windowName) - if err != nil { - return err - } - - t.wcex = &wndClassEx{ - Style: CS_HREDRAW | CS_VREDRAW, - WndProc: windows.NewCallback(t.wndProc), - Instance: t.instance, - Icon: t.icon, - Cursor: t.cursor, - Background: windows.Handle(6), // (COLOR_WINDOW + 1) - ClassName: classNamePtr, - IconSm: t.icon, - } - if err := t.wcex.register(); err != nil { - return err - } - - windowHandle, _, err := pCreateWindowEx.Call( - uintptr(0), - uintptr(unsafe.Pointer(classNamePtr)), - uintptr(unsafe.Pointer(windowNamePtr)), - uintptr(WS_OVERLAPPEDWINDOW), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(0), - uintptr(0), - uintptr(t.instance), - uintptr(0), - ) - if windowHandle == 0 { - return err - } - t.window = windows.Handle(windowHandle) - - pShowWindow.Call(uintptr(t.window), uintptr(SW_HIDE)) //nolint:errcheck - - boolRet, _, err := pUpdateWindow.Call(uintptr(t.window)) - if boolRet == 0 { - slog.Error(fmt.Sprintf("failed to update window: %s", err)) - } - - t.muNID.Lock() - defer t.muNID.Unlock() - t.nid = ¬ifyIconData{ - Wnd: t.window, - ID: 100, - Flags: NIF_MESSAGE, - CallbackMessage: t.wmSystrayMessage, - } - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.add() -} - -func (t *winTray) createMenu() error { - menuHandle, _, err := pCreatePopupMenu.Call() - if menuHandle == 0 { - return err - } - t.menus[0] = windows.Handle(menuHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647575(v=vs.85).aspx - mi := struct { - Size, Mask, Style, Max uint32 - Background windows.Handle - ContextHelpID uint32 - MenuData uintptr - }{ - Mask: MIM_APPLYTOSUBMENUS, - } - mi.Size = uint32(unsafe.Sizeof(mi)) - - res, _, err := pSetMenuInfo.Call( - uintptr(t.menus[0]), - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - return nil -} - -// Contains information about a menu item. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx -type menuItemInfo struct { - Size, Mask, Type, State uint32 - ID uint32 - SubMenu, Checked, Unchecked windows.Handle - ItemData uintptr - TypeData *uint16 - Cch uint32 - BMPItem windows.Handle -} - -func (t *winTray) addOrUpdateMenuItem(menuItemId uint32, parentId uint32, title string, disabled bool) error { - titlePtr, err := windows.UTF16PtrFromString(title) - if err != nil { - return err - } - - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_STATE, - Type: MFT_STRING, - ID: menuItemId, - TypeData: titlePtr, - Cch: uint32(len(title)), - } - mi.Size = uint32(unsafe.Sizeof(mi)) - if disabled { - mi.State |= MFS_DISABLED - } - - var res uintptr - t.muMenus.RLock() - menu := t.menus[parentId] - t.muMenus.RUnlock() - if t.getVisibleItemIndex(parentId, menuItemId) != -1 { - // We set the menu item info based on the menuID - boolRet, _, err := pSetMenuItemInfo.Call( - uintptr(menu), - uintptr(menuItemId), - 0, - uintptr(unsafe.Pointer(&mi)), - ) - if boolRet == 0 { - return fmt.Errorf("failed to set menu item: %w", err) - } - } - - if res == 0 { - // Menu item does not already exist, create it - t.muMenus.RLock() - submenu, exists := t.menus[menuItemId] - t.muMenus.RUnlock() - if exists { - mi.Mask |= MIIM_SUBMENU - mi.SubMenu = submenu - } - t.addToVisibleItems(parentId, menuItemId) - position := t.getVisibleItemIndex(parentId, menuItemId) - res, _, err = pInsertMenuItem.Call( - uintptr(menu), - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - t.delFromVisibleItems(parentId, menuItemId) - return err - } - t.muMenuOf.Lock() - t.menuOf[menuItemId] = menu - t.muMenuOf.Unlock() - } - - return nil -} - -func (t *winTray) addSeparatorMenuItem(menuItemId, parentId uint32) error { - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_ID | MIIM_STATE, - Type: MFT_SEPARATOR, - ID: menuItemId, - } - - mi.Size = uint32(unsafe.Sizeof(mi)) - - t.addToVisibleItems(parentId, menuItemId) - position := t.getVisibleItemIndex(parentId, menuItemId) - t.muMenus.RLock() - menu := uintptr(t.menus[parentId]) - t.muMenus.RUnlock() - res, _, err := pInsertMenuItem.Call( - menu, - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - - return nil -} - -// func (t *winTray) hideMenuItem(menuItemId, parentId uint32) error { -// const ERROR_SUCCESS syscall.Errno = 0 - -// t.muMenus.RLock() -// menu := uintptr(t.menus[parentId]) -// t.muMenus.RUnlock() -// res, _, err := pRemoveMenu.Call( -// menu, -// uintptr(menuItemId), -// MF_BYCOMMAND, -// ) -// if res == 0 && err.(syscall.Errno) != ERROR_SUCCESS { -// return err -// } -// t.delFromVisibleItems(parentId, menuItemId) - -// return nil -// } - -func (t *winTray) showMenu() error { - p := point{} - boolRet, _, err := pGetCursorPos.Call(uintptr(unsafe.Pointer(&p))) - if boolRet == 0 { - return err - } - boolRet, _, err = pSetForegroundWindow.Call(uintptr(t.window)) - if boolRet == 0 { - slog.Warn(fmt.Sprintf("failed to bring menu to foreground: %s", err)) - } - - boolRet, _, err = pTrackPopupMenu.Call( - uintptr(t.menus[0]), - TPM_BOTTOMALIGN|TPM_LEFTALIGN, - uintptr(p.X), - uintptr(p.Y), - 0, - uintptr(t.window), - 0, - ) - if boolRet == 0 { - return err - } - - return nil -} - -func (t *winTray) delFromVisibleItems(parent, val uint32) { - t.muVisibleItems.Lock() - defer t.muVisibleItems.Unlock() - visibleItems := t.visibleItems[parent] - for i, itemval := range visibleItems { - if val == itemval { - t.visibleItems[parent] = append(visibleItems[:i], visibleItems[i+1:]...) - break - } - } -} - -func (t *winTray) addToVisibleItems(parent, val uint32) { - t.muVisibleItems.Lock() - defer t.muVisibleItems.Unlock() - if visibleItems, exists := t.visibleItems[parent]; !exists { - t.visibleItems[parent] = []uint32{val} - } else { - newvisible := append(visibleItems, val) - sort.Slice(newvisible, func(i, j int) bool { return newvisible[i] < newvisible[j] }) - t.visibleItems[parent] = newvisible - } -} - -func (t *winTray) getVisibleItemIndex(parent, val uint32) int { - t.muVisibleItems.RLock() - defer t.muVisibleItems.RUnlock() - for i, itemval := range t.visibleItems[parent] { - if val == itemval { - return i - } - } - return -1 -} - -func iconBytesToFilePath(iconBytes []byte) (string, error) { - bh := md5.Sum(iconBytes) - dataHash := hex.EncodeToString(bh[:]) - iconFilePath := filepath.Join(os.TempDir(), "ollama_temp_icon_"+dataHash) - - if _, err := os.Stat(iconFilePath); os.IsNotExist(err) { - if err := os.WriteFile(iconFilePath, iconBytes, 0o644); err != nil { - return "", err - } - } - return iconFilePath, nil -} - -// Loads an image from file and shows it in tray. -// Shell_NotifyIcon: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159(v=vs.85).aspx -func (t *winTray) setIcon(src string) error { - h, err := t.loadIconFrom(src) - if err != nil { - return err - } - - t.muNID.Lock() - defer t.muNID.Unlock() - t.nid.Icon = h - t.nid.Flags |= NIF_ICON - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.modify() -} - -// Loads an image from file to be shown in tray or menu item. -// LoadImage: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx -func (t *winTray) loadIconFrom(src string) (windows.Handle, error) { - // Save and reuse handles of loaded images - t.muLoadedImages.RLock() - h, ok := t.loadedImages[src] - t.muLoadedImages.RUnlock() - if !ok { - srcPtr, err := windows.UTF16PtrFromString(src) - if err != nil { - return 0, err - } - res, _, err := pLoadImage.Call( - 0, - uintptr(unsafe.Pointer(srcPtr)), - IMAGE_ICON, - 0, - 0, - LR_LOADFROMFILE|LR_DEFAULTSIZE, - ) - if res == 0 { - return 0, err - } - h = windows.Handle(res) - t.muLoadedImages.Lock() - t.loadedImages[src] = h - t.muLoadedImages.Unlock() - } - return h, nil -} - -func (t *winTray) DisplayFirstUseNotification() error { - t.muNID.Lock() - defer t.muNID.Unlock() - copy(t.nid.InfoTitle[:], windows.StringToUTF16(firstTimeTitle)) - copy(t.nid.Info[:], windows.StringToUTF16(firstTimeMessage)) - t.nid.Flags |= NIF_INFO - t.nid.Size = uint32(unsafe.Sizeof(*wt.nid)) - - return t.nid.modify() -} diff --git a/ollama/app/tray/wintray/w32api.go b/ollama/app/tray/wintray/w32api.go deleted file mode 100755 index a1e0381..0000000 --- a/ollama/app/tray/wintray/w32api.go +++ /dev/null @@ -1,89 +0,0 @@ -//go:build windows - -package wintray - -import ( - "runtime" - - "golang.org/x/sys/windows" -) - -var ( - k32 = windows.NewLazySystemDLL("Kernel32.dll") - u32 = windows.NewLazySystemDLL("User32.dll") - s32 = windows.NewLazySystemDLL("Shell32.dll") - - pCreatePopupMenu = u32.NewProc("CreatePopupMenu") - pCreateWindowEx = u32.NewProc("CreateWindowExW") - pDefWindowProc = u32.NewProc("DefWindowProcW") - pDestroyWindow = u32.NewProc("DestroyWindow") - pDispatchMessage = u32.NewProc("DispatchMessageW") - pGetCursorPos = u32.NewProc("GetCursorPos") - pGetMessage = u32.NewProc("GetMessageW") - pGetModuleHandle = k32.NewProc("GetModuleHandleW") - pInsertMenuItem = u32.NewProc("InsertMenuItemW") - pLoadCursor = u32.NewProc("LoadCursorW") - pLoadIcon = u32.NewProc("LoadIconW") - pLoadImage = u32.NewProc("LoadImageW") - pPostMessage = u32.NewProc("PostMessageW") - pPostQuitMessage = u32.NewProc("PostQuitMessage") - pRegisterClass = u32.NewProc("RegisterClassExW") - pRegisterWindowMessage = u32.NewProc("RegisterWindowMessageW") - pSetForegroundWindow = u32.NewProc("SetForegroundWindow") - pSetMenuInfo = u32.NewProc("SetMenuInfo") - pSetMenuItemInfo = u32.NewProc("SetMenuItemInfoW") - pShellNotifyIcon = s32.NewProc("Shell_NotifyIconW") - pShowWindow = u32.NewProc("ShowWindow") - pTrackPopupMenu = u32.NewProc("TrackPopupMenu") - pTranslateMessage = u32.NewProc("TranslateMessage") - pUnregisterClass = u32.NewProc("UnregisterClassW") - pUpdateWindow = u32.NewProc("UpdateWindow") -) - -const ( - CS_HREDRAW = 0x0002 - CS_VREDRAW = 0x0001 - CW_USEDEFAULT = 0x80000000 - IDC_ARROW = 32512 // Standard arrow - IDI_APPLICATION = 32512 - IMAGE_ICON = 1 // Loads an icon - LR_DEFAULTSIZE = 0x00000040 // Loads default-size icon for windows(SM_CXICON x SM_CYICON) if cx, cy are set to zero - LR_LOADFROMFILE = 0x00000010 // Loads the stand-alone image from the file - MF_BYCOMMAND = 0x00000000 - MFS_DISABLED = 0x00000003 - MFT_SEPARATOR = 0x00000800 - MFT_STRING = 0x00000000 - MIIM_BITMAP = 0x00000080 - MIIM_FTYPE = 0x00000100 - MIIM_ID = 0x00000002 - MIIM_STATE = 0x00000001 - MIIM_STRING = 0x00000040 - MIIM_SUBMENU = 0x00000004 - MIM_APPLYTOSUBMENUS = 0x80000000 - NIF_ICON = 0x00000002 - NIF_INFO = 0x00000010 - NIF_MESSAGE = 0x00000001 - SW_HIDE = 0 - TPM_BOTTOMALIGN = 0x0020 - TPM_LEFTALIGN = 0x0000 - WM_CLOSE = 0x0010 - WM_USER = 0x0400 - WS_CAPTION = 0x00C00000 - WS_MAXIMIZEBOX = 0x00010000 - WS_MINIMIZEBOX = 0x00020000 - WS_OVERLAPPED = 0x00000000 - WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX - WS_SYSMENU = 0x00080000 - WS_THICKFRAME = 0x00040000 -) - -// Not sure if this is actually needed on windows -func init() { - runtime.LockOSThread() -} - -// The POINT structure defines the x- and y- coordinates of a point. -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -type point struct { - X, Y int32 -} diff --git a/ollama/app/tray/wintray/winclass.go b/ollama/app/tray/wintray/winclass.go deleted file mode 100755 index 9ce71d0..0000000 --- a/ollama/app/tray/wintray/winclass.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build windows - -package wintray - -import ( - "unsafe" - - "golang.org/x/sys/windows" -) - -// Contains window class information. -// It is used with the RegisterClassEx and GetClassInfoEx functions. -// https://msdn.microsoft.com/en-us/library/ms633577.aspx -type wndClassEx struct { - Size, Style uint32 - WndProc uintptr - ClsExtra, WndExtra int32 - Instance, Icon, Cursor, Background windows.Handle - MenuName, ClassName *uint16 - IconSm windows.Handle -} - -// Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function. -// https://msdn.microsoft.com/en-us/library/ms633587.aspx -func (w *wndClassEx) register() error { - w.Size = uint32(unsafe.Sizeof(*w)) - res, _, err := pRegisterClass.Call(uintptr(unsafe.Pointer(w))) - if res == 0 { - return err - } - return nil -} - -// Unregisters a window class, freeing the memory required for the class. -// https://msdn.microsoft.com/en-us/library/ms644899.aspx -func (w *wndClassEx) unregister() error { - res, _, err := pUnregisterClass.Call( - uintptr(unsafe.Pointer(w.ClassName)), - uintptr(w.Instance), - ) - if res == 0 { - return err - } - return nil -} diff --git a/ollama/auth/auth.go b/ollama/auth/auth.go deleted file mode 100755 index e1d8541..0000000 --- a/ollama/auth/auth.go +++ /dev/null @@ -1,92 +0,0 @@ -package auth - -import ( - "bytes" - "context" - "crypto/rand" - "encoding/base64" - "errors" - "fmt" - "io" - "log/slog" - "os" - "path/filepath" - "strings" - - "golang.org/x/crypto/ssh" -) - -const defaultPrivateKey = "id_ed25519" - -func keyPath() (string, error) { - home, err := os.UserHomeDir() - if err != nil { - return "", err - } - - return filepath.Join(home, ".ollama", defaultPrivateKey), nil -} - -func GetPublicKey() (string, error) { - keyPath, err := keyPath() - if err != nil { - return "", err - } - - privateKeyFile, err := os.ReadFile(keyPath) - if err != nil { - slog.Info(fmt.Sprintf("Failed to load private key: %v", err)) - return "", err - } - - privateKey, err := ssh.ParsePrivateKey(privateKeyFile) - if err != nil { - return "", err - } - - publicKey := ssh.MarshalAuthorizedKey(privateKey.PublicKey()) - - return strings.TrimSpace(string(publicKey)), nil -} - -func NewNonce(r io.Reader, length int) (string, error) { - nonce := make([]byte, length) - if _, err := io.ReadFull(r, nonce); err != nil { - return "", err - } - - return base64.RawURLEncoding.EncodeToString(nonce), nil -} - -func Sign(ctx context.Context, bts []byte) (string, error) { - keyPath, err := keyPath() - if err != nil { - return "", err - } - - privateKeyFile, err := os.ReadFile(keyPath) - if err != nil { - slog.Info(fmt.Sprintf("Failed to load private key: %v", err)) - return "", err - } - - privateKey, err := ssh.ParsePrivateKey(privateKeyFile) - if err != nil { - return "", err - } - - // get the pubkey, but remove the type - publicKey := ssh.MarshalAuthorizedKey(privateKey.PublicKey()) - parts := bytes.Split(publicKey, []byte(" ")) - if len(parts) < 2 { - return "", errors.New("malformed public key") - } - - signedData, err := privateKey.Sign(rand.Reader, bts) - if err != nil { - return "", err - } - - // signature is : - return fmt.Sprintf("%s:%s", bytes.TrimSpace(parts[1]), base64.StdEncoding.EncodeToString(signedData.Blob)), nil -} diff --git a/ollama/cmd/cmd.go b/ollama/cmd/cmd.go deleted file mode 100755 index d47db65..0000000 --- a/ollama/cmd/cmd.go +++ /dev/null @@ -1,1383 +0,0 @@ -package cmd - -import ( - "archive/zip" - "bytes" - "context" - "crypto/ed25519" - "crypto/rand" - "crypto/sha256" - "encoding/pem" - "errors" - "fmt" - "io" - "log" - "math" - "net" - "net/http" - "os" - "os/signal" - "path/filepath" - "regexp" - "runtime" - "slices" - "strings" - "syscall" - "time" - - "github.com/containerd/console" - "github.com/mattn/go-runewidth" - "github.com/olekukonko/tablewriter" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh" - "golang.org/x/term" - - "github.com/ollama/ollama/api" - "github.com/ollama/ollama/auth" - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/format" - "github.com/ollama/ollama/parser" - "github.com/ollama/ollama/progress" - "github.com/ollama/ollama/server" - "github.com/ollama/ollama/types/errtypes" - "github.com/ollama/ollama/types/model" - "github.com/ollama/ollama/version" -) - -func CreateHandler(cmd *cobra.Command, args []string) error { - filename, _ := cmd.Flags().GetString("file") - filename, err := filepath.Abs(filename) - if err != nil { - return err - } - - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - p := progress.NewProgress(os.Stderr) - defer p.Stop() - - f, err := os.Open(filename) - if err != nil { - return err - } - defer f.Close() - - modelfile, err := parser.ParseFile(f) - if err != nil { - return err - } - - home, err := os.UserHomeDir() - if err != nil { - return err - } - - status := "transferring model data" - spinner := progress.NewSpinner(status) - p.Add(status, spinner) - - for i := range modelfile.Commands { - switch modelfile.Commands[i].Name { - case "model", "adapter": - path := modelfile.Commands[i].Args - if path == "~" { - path = home - } else if strings.HasPrefix(path, "~/") { - path = filepath.Join(home, path[2:]) - } - - if !filepath.IsAbs(path) { - path = filepath.Join(filepath.Dir(filename), path) - } - - fi, err := os.Stat(path) - if errors.Is(err, os.ErrNotExist) && modelfile.Commands[i].Name == "model" { - continue - } else if err != nil { - return err - } - - if fi.IsDir() { - // this is likely a safetensors or pytorch directory - // TODO make this work w/ adapters - tempfile, err := tempZipFiles(path) - if err != nil { - return err - } - defer os.RemoveAll(tempfile) - - path = tempfile - } - - digest, err := createBlob(cmd, client, path) - if err != nil { - return err - } - - modelfile.Commands[i].Args = "@" + digest - } - } - - bars := make(map[string]*progress.Bar) - fn := func(resp api.ProgressResponse) error { - if resp.Digest != "" { - spinner.Stop() - - bar, ok := bars[resp.Digest] - if !ok { - bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed) - bars[resp.Digest] = bar - p.Add(resp.Digest, bar) - } - - bar.Set(resp.Completed) - } else if status != resp.Status { - spinner.Stop() - - status = resp.Status - spinner = progress.NewSpinner(status) - p.Add(status, spinner) - } - - return nil - } - - quantize, _ := cmd.Flags().GetString("quantize") - - request := api.CreateRequest{Name: args[0], Modelfile: modelfile.String(), Quantize: quantize} - if err := client.Create(cmd.Context(), &request, fn); err != nil { - return err - } - - return nil -} - -func tempZipFiles(path string) (string, error) { - tempfile, err := os.CreateTemp("", "ollama-tf") - if err != nil { - return "", err - } - defer tempfile.Close() - - detectContentType := func(path string) (string, error) { - f, err := os.Open(path) - if err != nil { - return "", err - } - defer f.Close() - - var b bytes.Buffer - b.Grow(512) - - if _, err := io.CopyN(&b, f, 512); err != nil && !errors.Is(err, io.EOF) { - return "", err - } - - contentType, _, _ := strings.Cut(http.DetectContentType(b.Bytes()), ";") - return contentType, nil - } - - glob := func(pattern, contentType string) ([]string, error) { - matches, err := filepath.Glob(pattern) - if err != nil { - return nil, err - } - - for _, safetensor := range matches { - if ct, err := detectContentType(safetensor); err != nil { - return nil, err - } else if ct != contentType { - return nil, fmt.Errorf("invalid content type: expected %s for %s", ct, safetensor) - } - } - - return matches, nil - } - - var files []string - if st, _ := glob(filepath.Join(path, "model*.safetensors"), "application/octet-stream"); len(st) > 0 { - // safetensors files might be unresolved git lfs references; skip if they are - // covers model-x-of-y.safetensors, model.fp32-x-of-y.safetensors, model.safetensors - files = append(files, st...) - } else if pt, _ := glob(filepath.Join(path, "pytorch_model*.bin"), "application/zip"); len(pt) > 0 { - // pytorch files might also be unresolved git lfs references; skip if they are - // covers pytorch_model-x-of-y.bin, pytorch_model.fp32-x-of-y.bin, pytorch_model.bin - files = append(files, pt...) - } else if pt, _ := glob(filepath.Join(path, "consolidated*.pth"), "application/zip"); len(pt) > 0 { - // pytorch files might also be unresolved git lfs references; skip if they are - // covers consolidated.x.pth, consolidated.pth - files = append(files, pt...) - } else { - return "", errors.New("no safetensors or torch files found") - } - - // add configuration files, json files are detected as text/plain - js, err := glob(filepath.Join(path, "*.json"), "text/plain") - if err != nil { - return "", err - } - files = append(files, js...) - - if tks, _ := glob(filepath.Join(path, "tokenizer.model"), "application/octet-stream"); len(tks) > 0 { - // add tokenizer.model if it exists, tokenizer.json is automatically picked up by the previous glob - // tokenizer.model might be a unresolved git lfs reference; error if it is - files = append(files, tks...) - } else if tks, _ := glob(filepath.Join(path, "**/tokenizer.model"), "text/plain"); len(tks) > 0 { - // some times tokenizer.model is in a subdirectory (e.g. meta-llama/Meta-Llama-3-8B) - files = append(files, tks...) - } - - zipfile := zip.NewWriter(tempfile) - defer zipfile.Close() - - for _, file := range files { - f, err := os.Open(file) - if err != nil { - return "", err - } - defer f.Close() - - fi, err := f.Stat() - if err != nil { - return "", err - } - - zfi, err := zip.FileInfoHeader(fi) - if err != nil { - return "", err - } - - zf, err := zipfile.CreateHeader(zfi) - if err != nil { - return "", err - } - - if _, err := io.Copy(zf, f); err != nil { - return "", err - } - } - - return tempfile.Name(), nil -} - -func createBlob(cmd *cobra.Command, client *api.Client, path string) (string, error) { - bin, err := os.Open(path) - if err != nil { - return "", err - } - defer bin.Close() - - hash := sha256.New() - if _, err := io.Copy(hash, bin); err != nil { - return "", err - } - - if _, err := bin.Seek(0, io.SeekStart); err != nil { - return "", err - } - - digest := fmt.Sprintf("sha256:%x", hash.Sum(nil)) - if err = client.CreateBlob(cmd.Context(), digest, bin); err != nil { - return "", err - } - return digest, nil -} - -func RunHandler(cmd *cobra.Command, args []string) error { - interactive := true - - opts := runOptions{ - Model: args[0], - WordWrap: os.Getenv("TERM") == "xterm-256color", - Options: map[string]interface{}{}, - } - - format, err := cmd.Flags().GetString("format") - if err != nil { - return err - } - opts.Format = format - - keepAlive, err := cmd.Flags().GetString("keepalive") - if err != nil { - return err - } - if keepAlive != "" { - d, err := time.ParseDuration(keepAlive) - if err != nil { - return err - } - opts.KeepAlive = &api.Duration{Duration: d} - } - - prompts := args[1:] - // prepend stdin to the prompt if provided - if !term.IsTerminal(int(os.Stdin.Fd())) { - in, err := io.ReadAll(os.Stdin) - if err != nil { - return err - } - - prompts = append([]string{string(in)}, prompts...) - opts.WordWrap = false - interactive = false - } - opts.Prompt = strings.Join(prompts, " ") - if len(prompts) > 0 { - interactive = false - } - - nowrap, err := cmd.Flags().GetBool("nowordwrap") - if err != nil { - return err - } - opts.WordWrap = !nowrap - - // Fill out the rest of the options based on information about the - // model. - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - name := args[0] - info, err := func() (*api.ShowResponse, error) { - showReq := &api.ShowRequest{Name: name} - info, err := client.Show(cmd.Context(), showReq) - var se api.StatusError - if errors.As(err, &se) && se.StatusCode == http.StatusNotFound { - if err := PullHandler(cmd, []string{name}); err != nil { - return nil, err - } - return client.Show(cmd.Context(), &api.ShowRequest{Name: name}) - } - return info, err - }() - if err != nil { - return err - } - - opts.MultiModal = slices.Contains(info.Details.Families, "clip") - opts.ParentModel = info.Details.ParentModel - - if interactive { - if err := loadModel(cmd, &opts); err != nil { - return err - } - - for _, msg := range info.Messages { - switch msg.Role { - case "user": - fmt.Printf(">>> %s\n", msg.Content) - case "assistant": - state := &displayResponseState{} - displayResponse(msg.Content, opts.WordWrap, state) - fmt.Println() - fmt.Println() - } - } - - return generateInteractive(cmd, opts) - } - return generate(cmd, opts) -} - -func errFromUnknownKey(unknownKeyErr error) error { - // find SSH public key in the error message - sshKeyPattern := `ssh-\w+ [^\s"]+` - re := regexp.MustCompile(sshKeyPattern) - matches := re.FindStringSubmatch(unknownKeyErr.Error()) - - if len(matches) > 0 { - serverPubKey := matches[0] - - localPubKey, err := auth.GetPublicKey() - if err != nil { - return unknownKeyErr - } - - if runtime.GOOS == "linux" && serverPubKey != localPubKey { - // try the ollama service public key - svcPubKey, err := os.ReadFile("/usr/share/ollama/.ollama/id_ed25519.pub") - if err != nil { - return unknownKeyErr - } - localPubKey = strings.TrimSpace(string(svcPubKey)) - } - - // check if the returned public key matches the local public key, this prevents adding a remote key to the user's account - if serverPubKey != localPubKey { - return unknownKeyErr - } - - var msg strings.Builder - msg.WriteString(unknownKeyErr.Error()) - msg.WriteString("\n\nYour ollama key is:\n") - msg.WriteString(localPubKey) - msg.WriteString("\nAdd your key at:\n") - msg.WriteString("https://ollama.com/settings/keys") - - return errors.New(msg.String()) - } - - return unknownKeyErr -} - -func PushHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - insecure, err := cmd.Flags().GetBool("insecure") - if err != nil { - return err - } - - p := progress.NewProgress(os.Stderr) - defer p.Stop() - - bars := make(map[string]*progress.Bar) - var status string - var spinner *progress.Spinner - - fn := func(resp api.ProgressResponse) error { - if resp.Digest != "" { - if spinner != nil { - spinner.Stop() - } - - bar, ok := bars[resp.Digest] - if !ok { - bar = progress.NewBar(fmt.Sprintf("pushing %s...", resp.Digest[7:19]), resp.Total, resp.Completed) - bars[resp.Digest] = bar - p.Add(resp.Digest, bar) - } - - bar.Set(resp.Completed) - } else if status != resp.Status { - if spinner != nil { - spinner.Stop() - } - - status = resp.Status - spinner = progress.NewSpinner(status) - p.Add(status, spinner) - } - - return nil - } - - request := api.PushRequest{Name: args[0], Insecure: insecure} - if err := client.Push(cmd.Context(), &request, fn); err != nil { - if spinner != nil { - spinner.Stop() - } - if strings.Contains(err.Error(), "access denied") { - return errors.New("you are not authorized to push to this namespace, create the model under a namespace you own") - } - host := model.ParseName(args[0]).Host - isOllamaHost := strings.HasSuffix(host, ".ollama.ai") || strings.HasSuffix(host, ".ollama.com") - if strings.Contains(err.Error(), errtypes.UnknownOllamaKeyErrMsg) && isOllamaHost { - // the user has not added their ollama key to ollama.com - // re-throw an error with a more user-friendly message - return errFromUnknownKey(err) - } - - return err - } - - spinner.Stop() - return nil -} - -func ListHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - models, err := client.List(cmd.Context()) - if err != nil { - return err - } - - var data [][]string - - for _, m := range models.Models { - if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) { - data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), format.HumanTime(m.ModifiedAt, "Never")}) - } - } - - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"NAME", "ID", "SIZE", "MODIFIED"}) - table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) - table.SetAlignment(tablewriter.ALIGN_LEFT) - table.SetHeaderLine(false) - table.SetBorder(false) - table.SetNoWhiteSpace(true) - table.SetTablePadding("\t") - table.AppendBulk(data) - table.Render() - - return nil -} - -func ListRunningHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - models, err := client.ListRunning(cmd.Context()) - if err != nil { - return err - } - - var data [][]string - - for _, m := range models.Models { - if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) { - var procStr string - switch { - case m.SizeVRAM == 0: - procStr = "100% CPU" - case m.SizeVRAM == m.Size: - procStr = "100% GPU" - case m.SizeVRAM > m.Size || m.Size == 0: - procStr = "Unknown" - default: - sizeCPU := m.Size - m.SizeVRAM - cpuPercent := math.Round(float64(sizeCPU) / float64(m.Size) * 100) - procStr = fmt.Sprintf("%d%%/%d%% CPU/GPU", int(cpuPercent), int(100-cpuPercent)) - } - data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), procStr, format.HumanTime(m.ExpiresAt, "Never")}) - } - } - - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"NAME", "ID", "SIZE", "PROCESSOR", "UNTIL"}) - table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) - table.SetAlignment(tablewriter.ALIGN_LEFT) - table.SetHeaderLine(false) - table.SetBorder(false) - table.SetNoWhiteSpace(true) - table.SetTablePadding("\t") - table.AppendBulk(data) - table.Render() - - return nil -} - -func DeleteHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - for _, name := range args { - req := api.DeleteRequest{Name: name} - if err := client.Delete(cmd.Context(), &req); err != nil { - return err - } - fmt.Printf("deleted '%s'\n", name) - } - return nil -} - -func ShowHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - license, errLicense := cmd.Flags().GetBool("license") - modelfile, errModelfile := cmd.Flags().GetBool("modelfile") - parameters, errParams := cmd.Flags().GetBool("parameters") - system, errSystem := cmd.Flags().GetBool("system") - template, errTemplate := cmd.Flags().GetBool("template") - - for _, boolErr := range []error{errLicense, errModelfile, errParams, errSystem, errTemplate} { - if boolErr != nil { - return errors.New("error retrieving flags") - } - } - - flagsSet := 0 - showType := "" - - if license { - flagsSet++ - showType = "license" - } - - if modelfile { - flagsSet++ - showType = "modelfile" - } - - if parameters { - flagsSet++ - showType = "parameters" - } - - if system { - flagsSet++ - showType = "system" - } - - if template { - flagsSet++ - showType = "template" - } - - if flagsSet > 1 { - return errors.New("only one of '--license', '--modelfile', '--parameters', '--system', or '--template' can be specified") - } - - req := api.ShowRequest{Name: args[0]} - resp, err := client.Show(cmd.Context(), &req) - if err != nil { - return err - } - - if flagsSet == 1 { - switch showType { - case "license": - fmt.Println(resp.License) - case "modelfile": - fmt.Println(resp.Modelfile) - case "parameters": - fmt.Println(resp.Parameters) - case "system": - fmt.Println(resp.System) - case "template": - fmt.Println(resp.Template) - } - - return nil - } - - showInfo(resp) - - return nil -} - -func showInfo(resp *api.ShowResponse) { - arch := resp.ModelInfo["general.architecture"].(string) - - modelData := [][]string{ - {"arch", arch}, - {"parameters", resp.Details.ParameterSize}, - {"quantization", resp.Details.QuantizationLevel}, - {"context length", fmt.Sprintf("%v", resp.ModelInfo[fmt.Sprintf("%s.context_length", arch)].(float64))}, - {"embedding length", fmt.Sprintf("%v", resp.ModelInfo[fmt.Sprintf("%s.embedding_length", arch)].(float64))}, - } - - mainTableData := [][]string{ - {"Model"}, - {renderSubTable(modelData, false)}, - } - - if resp.ProjectorInfo != nil { - projectorData := [][]string{ - {"arch", "clip"}, - {"parameters", format.HumanNumber(uint64(resp.ProjectorInfo["general.parameter_count"].(float64)))}, - } - - if projectorType, ok := resp.ProjectorInfo["clip.projector_type"]; ok { - projectorData = append(projectorData, []string{"projector type", projectorType.(string)}) - } - - projectorData = append(projectorData, - []string{"embedding length", fmt.Sprintf("%v", resp.ProjectorInfo["clip.vision.embedding_length"].(float64))}, - []string{"projection dimensionality", fmt.Sprintf("%v", resp.ProjectorInfo["clip.vision.projection_dim"].(float64))}, - ) - - mainTableData = append(mainTableData, - []string{"Projector"}, - []string{renderSubTable(projectorData, false)}, - ) - } - - if resp.Parameters != "" { - mainTableData = append(mainTableData, []string{"Parameters"}, []string{formatParams(resp.Parameters)}) - } - - if resp.System != "" { - mainTableData = append(mainTableData, []string{"System"}, []string{renderSubTable(twoLines(resp.System), true)}) - } - - if resp.License != "" { - mainTableData = append(mainTableData, []string{"License"}, []string{renderSubTable(twoLines(resp.License), true)}) - } - - table := tablewriter.NewWriter(os.Stdout) - table.SetAutoWrapText(false) - table.SetBorder(false) - table.SetAlignment(tablewriter.ALIGN_LEFT) - - for _, v := range mainTableData { - table.Append(v) - } - - table.Render() -} - -func renderSubTable(data [][]string, file bool) string { - var buf bytes.Buffer - table := tablewriter.NewWriter(&buf) - table.SetAutoWrapText(!file) - table.SetBorder(false) - table.SetNoWhiteSpace(true) - table.SetTablePadding("\t") - table.SetAlignment(tablewriter.ALIGN_LEFT) - - for _, v := range data { - table.Append(v) - } - - table.Render() - - renderedTable := buf.String() - lines := strings.Split(renderedTable, "\n") - for i, line := range lines { - lines[i] = "\t" + line - } - - return strings.Join(lines, "\n") -} - -func twoLines(s string) [][]string { - lines := strings.Split(s, "\n") - res := [][]string{} - - count := 0 - for _, line := range lines { - line = strings.TrimSpace(line) - if line != "" { - count++ - res = append(res, []string{line}) - if count == 2 { - return res - } - } - } - return res -} - -func formatParams(s string) string { - lines := strings.Split(s, "\n") - table := [][]string{} - - for _, line := range lines { - table = append(table, strings.Fields(line)) - } - return renderSubTable(table, false) -} - -func CopyHandler(cmd *cobra.Command, args []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - req := api.CopyRequest{Source: args[0], Destination: args[1]} - if err := client.Copy(cmd.Context(), &req); err != nil { - return err - } - fmt.Printf("copied '%s' to '%s'\n", args[0], args[1]) - return nil -} - -func PullHandler(cmd *cobra.Command, args []string) error { - insecure, err := cmd.Flags().GetBool("insecure") - if err != nil { - return err - } - - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - p := progress.NewProgress(os.Stderr) - defer p.Stop() - - bars := make(map[string]*progress.Bar) - - var status string - var spinner *progress.Spinner - - fn := func(resp api.ProgressResponse) error { - if resp.Digest != "" { - if spinner != nil { - spinner.Stop() - } - - bar, ok := bars[resp.Digest] - if !ok { - bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed) - bars[resp.Digest] = bar - p.Add(resp.Digest, bar) - } - - bar.Set(resp.Completed) - } else if status != resp.Status { - if spinner != nil { - spinner.Stop() - } - - status = resp.Status - spinner = progress.NewSpinner(status) - p.Add(status, spinner) - } - - return nil - } - - request := api.PullRequest{Name: args[0], Insecure: insecure} - if err := client.Pull(cmd.Context(), &request, fn); err != nil { - return err - } - - return nil -} - -type generateContextKey string - -type runOptions struct { - Model string - ParentModel string - Prompt string - Messages []api.Message - WordWrap bool - Format string - System string - Images []api.ImageData - Options map[string]interface{} - MultiModal bool - KeepAlive *api.Duration -} - -type displayResponseState struct { - lineLength int - wordBuffer string -} - -func displayResponse(content string, wordWrap bool, state *displayResponseState) { - termWidth, _, _ := term.GetSize(int(os.Stdout.Fd())) - if wordWrap && termWidth >= 10 { - for _, ch := range content { - if state.lineLength+1 > termWidth-5 { - if runewidth.StringWidth(state.wordBuffer) > termWidth-10 { - fmt.Printf("%s%c", state.wordBuffer, ch) - state.wordBuffer = "" - state.lineLength = 0 - continue - } - - // backtrack the length of the last word and clear to the end of the line - a := runewidth.StringWidth(state.wordBuffer) - if a > 0 { - fmt.Printf("\x1b[%dD", a) - } - fmt.Printf("\x1b[K\n") - fmt.Printf("%s%c", state.wordBuffer, ch) - chWidth := runewidth.RuneWidth(ch) - - state.lineLength = runewidth.StringWidth(state.wordBuffer) + chWidth - } else { - fmt.Print(string(ch)) - state.lineLength += runewidth.RuneWidth(ch) - if runewidth.RuneWidth(ch) >= 2 { - state.wordBuffer = "" - continue - } - - switch ch { - case ' ': - state.wordBuffer = "" - case '\n': - state.lineLength = 0 - default: - state.wordBuffer += string(ch) - } - } - } - } else { - fmt.Printf("%s%s", state.wordBuffer, content) - if len(state.wordBuffer) > 0 { - state.wordBuffer = "" - } - } -} - -func chat(cmd *cobra.Command, opts runOptions) (*api.Message, error) { - client, err := api.ClientFromEnvironment() - if err != nil { - return nil, err - } - - p := progress.NewProgress(os.Stderr) - defer p.StopAndClear() - - spinner := progress.NewSpinner("") - p.Add("", spinner) - - cancelCtx, cancel := context.WithCancel(cmd.Context()) - defer cancel() - - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGINT) - - go func() { - <-sigChan - cancel() - }() - - var state *displayResponseState = &displayResponseState{} - var latest api.ChatResponse - var fullResponse strings.Builder - var role string - - fn := func(response api.ChatResponse) error { - p.StopAndClear() - - latest = response - - role = response.Message.Role - content := response.Message.Content - fullResponse.WriteString(content) - - displayResponse(content, opts.WordWrap, state) - - return nil - } - - req := &api.ChatRequest{ - Model: opts.Model, - Messages: opts.Messages, - Format: opts.Format, - Options: opts.Options, - } - - if opts.KeepAlive != nil { - req.KeepAlive = opts.KeepAlive - } - - if err := client.Chat(cancelCtx, req, fn); err != nil { - if errors.Is(err, context.Canceled) { - return nil, nil - } - return nil, err - } - - if len(opts.Messages) > 0 { - fmt.Println() - fmt.Println() - } - - verbose, err := cmd.Flags().GetBool("verbose") - if err != nil { - return nil, err - } - - if verbose { - latest.Summary() - } - - return &api.Message{Role: role, Content: fullResponse.String()}, nil -} - -func generate(cmd *cobra.Command, opts runOptions) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - p := progress.NewProgress(os.Stderr) - defer p.StopAndClear() - - spinner := progress.NewSpinner("") - p.Add("", spinner) - - var latest api.GenerateResponse - - generateContext, ok := cmd.Context().Value(generateContextKey("context")).([]int) - if !ok { - generateContext = []int{} - } - - ctx, cancel := context.WithCancel(cmd.Context()) - defer cancel() - - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGINT) - - go func() { - <-sigChan - cancel() - }() - - var state *displayResponseState = &displayResponseState{} - - fn := func(response api.GenerateResponse) error { - p.StopAndClear() - - latest = response - content := response.Response - - displayResponse(content, opts.WordWrap, state) - - return nil - } - - if opts.MultiModal { - opts.Prompt, opts.Images, err = extractFileData(opts.Prompt) - if err != nil { - return err - } - } - - request := api.GenerateRequest{ - Model: opts.Model, - Prompt: opts.Prompt, - Context: generateContext, - Images: opts.Images, - Format: opts.Format, - System: opts.System, - Options: opts.Options, - KeepAlive: opts.KeepAlive, - } - - if err := client.Generate(ctx, &request, fn); err != nil { - if errors.Is(err, context.Canceled) { - return nil - } - return err - } - - if opts.Prompt != "" { - fmt.Println() - fmt.Println() - } - - if !latest.Done { - return nil - } - - verbose, err := cmd.Flags().GetBool("verbose") - if err != nil { - return err - } - - if verbose { - latest.Summary() - } - - ctx = context.WithValue(cmd.Context(), generateContextKey("context"), latest.Context) - cmd.SetContext(ctx) - - return nil -} - -func RunServer(cmd *cobra.Command, _ []string) error { - if err := initializeKeypair(); err != nil { - return err - } - - ln, err := net.Listen("tcp", envconfig.Host().Host) - if err != nil { - return err - } - - err = server.Serve(ln) - if errors.Is(err, http.ErrServerClosed) { - return nil - } - - return err -} - -func initializeKeypair() error { - home, err := os.UserHomeDir() - if err != nil { - return err - } - - privKeyPath := filepath.Join(home, ".ollama", "id_ed25519") - pubKeyPath := filepath.Join(home, ".ollama", "id_ed25519.pub") - - _, err = os.Stat(privKeyPath) - if os.IsNotExist(err) { - fmt.Printf("Couldn't find '%s'. Generating new private key.\n", privKeyPath) - cryptoPublicKey, cryptoPrivateKey, err := ed25519.GenerateKey(rand.Reader) - if err != nil { - return err - } - - privateKeyBytes, err := ssh.MarshalPrivateKey(cryptoPrivateKey, "") - if err != nil { - return err - } - - if err := os.MkdirAll(filepath.Dir(privKeyPath), 0o755); err != nil { - return fmt.Errorf("could not create directory %w", err) - } - - if err := os.WriteFile(privKeyPath, pem.EncodeToMemory(privateKeyBytes), 0o600); err != nil { - return err - } - - sshPublicKey, err := ssh.NewPublicKey(cryptoPublicKey) - if err != nil { - return err - } - - publicKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) - - if err := os.WriteFile(pubKeyPath, publicKeyBytes, 0o644); err != nil { - return err - } - - fmt.Printf("Your new public key is: \n\n%s\n", publicKeyBytes) - } - return nil -} - -func checkServerHeartbeat(cmd *cobra.Command, _ []string) error { - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - if err := client.Heartbeat(cmd.Context()); err != nil { - if !strings.Contains(err.Error(), " refused") { - return err - } - if err := startApp(cmd.Context(), client); err != nil { - return errors.New("could not connect to ollama app, is it running?") - } - } - return nil -} - -func versionHandler(cmd *cobra.Command, _ []string) { - client, err := api.ClientFromEnvironment() - if err != nil { - return - } - - serverVersion, err := client.Version(cmd.Context()) - if err != nil { - fmt.Println("Warning: could not connect to a running Ollama instance") - } - - if serverVersion != "" { - fmt.Printf("ollama version is %s\n", serverVersion) - } - - if serverVersion != version.Version { - fmt.Printf("Warning: client version is %s\n", version.Version) - } -} - -func appendEnvDocs(cmd *cobra.Command, envs []envconfig.EnvVar) { - if len(envs) == 0 { - return - } - - envUsage := ` -Environment Variables: -` - for _, e := range envs { - envUsage += fmt.Sprintf(" %-24s %s\n", e.Name, e.Description) - } - - cmd.SetUsageTemplate(cmd.UsageTemplate() + envUsage) -} - -func NewCLI() *cobra.Command { - log.SetFlags(log.LstdFlags | log.Lshortfile) - cobra.EnableCommandSorting = false - - if runtime.GOOS == "windows" { - console.ConsoleFromFile(os.Stdin) //nolint:errcheck - } - - rootCmd := &cobra.Command{ - Use: "ollama", - Short: "Large language model runner", - SilenceUsage: true, - SilenceErrors: true, - CompletionOptions: cobra.CompletionOptions{ - DisableDefaultCmd: true, - }, - Run: func(cmd *cobra.Command, args []string) { - if version, _ := cmd.Flags().GetBool("version"); version { - versionHandler(cmd, args) - return - } - - cmd.Print(cmd.UsageString()) - }, - } - - rootCmd.Flags().BoolP("version", "v", false, "Show version information") - - createCmd := &cobra.Command{ - Use: "create MODEL", - Short: "Create a model from a Modelfile", - Args: cobra.ExactArgs(1), - PreRunE: checkServerHeartbeat, - RunE: CreateHandler, - } - - createCmd.Flags().StringP("file", "f", "Modelfile", "Name of the Modelfile") - createCmd.Flags().StringP("quantize", "q", "", "Quantize model to this level (e.g. q4_0)") - - showCmd := &cobra.Command{ - Use: "show MODEL", - Short: "Show information for a model", - Args: cobra.ExactArgs(1), - PreRunE: checkServerHeartbeat, - RunE: ShowHandler, - } - - showCmd.Flags().Bool("license", false, "Show license of a model") - showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model") - showCmd.Flags().Bool("parameters", false, "Show parameters of a model") - showCmd.Flags().Bool("template", false, "Show template of a model") - showCmd.Flags().Bool("system", false, "Show system message of a model") - - runCmd := &cobra.Command{ - Use: "run MODEL [PROMPT]", - Short: "Run a model", - Args: cobra.MinimumNArgs(1), - PreRunE: checkServerHeartbeat, - RunE: RunHandler, - } - - runCmd.Flags().String("keepalive", "", "Duration to keep a model loaded (e.g. 5m)") - runCmd.Flags().Bool("verbose", false, "Show timings for response") - runCmd.Flags().Bool("insecure", false, "Use an insecure registry") - runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically") - runCmd.Flags().String("format", "", "Response format (e.g. json)") - serveCmd := &cobra.Command{ - Use: "serve", - Aliases: []string{"start"}, - Short: "Start ollama", - Args: cobra.ExactArgs(0), - RunE: RunServer, - } - - pullCmd := &cobra.Command{ - Use: "pull MODEL", - Short: "Pull a model from a registry", - Args: cobra.ExactArgs(1), - PreRunE: checkServerHeartbeat, - RunE: PullHandler, - } - - pullCmd.Flags().Bool("insecure", false, "Use an insecure registry") - - pushCmd := &cobra.Command{ - Use: "push MODEL", - Short: "Push a model to a registry", - Args: cobra.ExactArgs(1), - PreRunE: checkServerHeartbeat, - RunE: PushHandler, - } - - pushCmd.Flags().Bool("insecure", false, "Use an insecure registry") - - listCmd := &cobra.Command{ - Use: "list", - Aliases: []string{"ls"}, - Short: "List models", - PreRunE: checkServerHeartbeat, - RunE: ListHandler, - } - - psCmd := &cobra.Command{ - Use: "ps", - Short: "List running models", - PreRunE: checkServerHeartbeat, - RunE: ListRunningHandler, - } - - copyCmd := &cobra.Command{ - Use: "cp SOURCE DESTINATION", - Short: "Copy a model", - Args: cobra.ExactArgs(2), - PreRunE: checkServerHeartbeat, - RunE: CopyHandler, - } - - deleteCmd := &cobra.Command{ - Use: "rm MODEL [MODEL...]", - Short: "Remove a model", - Args: cobra.MinimumNArgs(1), - PreRunE: checkServerHeartbeat, - RunE: DeleteHandler, - } - - envVars := envconfig.AsMap() - - envs := []envconfig.EnvVar{envVars["OLLAMA_HOST"]} - - for _, cmd := range []*cobra.Command{ - createCmd, - showCmd, - runCmd, - pullCmd, - pushCmd, - listCmd, - psCmd, - copyCmd, - deleteCmd, - serveCmd, - } { - switch cmd { - case runCmd: - appendEnvDocs(cmd, []envconfig.EnvVar{envVars["OLLAMA_HOST"], envVars["OLLAMA_NOHISTORY"]}) - case serveCmd: - appendEnvDocs(cmd, []envconfig.EnvVar{ - envVars["OLLAMA_DEBUG"], - envVars["OLLAMA_HOST"], - envVars["OLLAMA_KEEP_ALIVE"], - envVars["OLLAMA_MAX_LOADED_MODELS"], - envVars["OLLAMA_MAX_QUEUE"], - envVars["OLLAMA_MODELS"], - envVars["OLLAMA_NUM_PARALLEL"], - envVars["OLLAMA_NOPRUNE"], - envVars["OLLAMA_ORIGINS"], - envVars["OLLAMA_SCHED_SPREAD"], - envVars["OLLAMA_TMPDIR"], - envVars["OLLAMA_FLASH_ATTENTION"], - envVars["OLLAMA_LLM_LIBRARY"], - }) - default: - appendEnvDocs(cmd, envs) - } - } - - rootCmd.AddCommand( - serveCmd, - createCmd, - showCmd, - runCmd, - pullCmd, - pushCmd, - listCmd, - psCmd, - copyCmd, - deleteCmd, - ) - - return rootCmd -} diff --git a/ollama/cmd/interactive.go b/ollama/cmd/interactive.go deleted file mode 100755 index 4462cf2..0000000 --- a/ollama/cmd/interactive.go +++ /dev/null @@ -1,622 +0,0 @@ -package cmd - -import ( - "cmp" - "errors" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "slices" - "strings" - - "github.com/spf13/cobra" - "golang.org/x/exp/maps" - - "github.com/ollama/ollama/api" - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/parser" - "github.com/ollama/ollama/progress" - "github.com/ollama/ollama/readline" - "github.com/ollama/ollama/types/errtypes" -) - -type MultilineState int - -const ( - MultilineNone MultilineState = iota - MultilinePrompt - MultilineSystem -) - -func loadModel(cmd *cobra.Command, opts *runOptions) error { - p := progress.NewProgress(os.Stderr) - defer p.StopAndClear() - - spinner := progress.NewSpinner("") - p.Add("", spinner) - - client, err := api.ClientFromEnvironment() - if err != nil { - return err - } - - chatReq := &api.ChatRequest{ - Model: opts.Model, - KeepAlive: opts.KeepAlive, - } - - return client.Chat(cmd.Context(), chatReq, func(api.ChatResponse) error { return nil }) -} - -func generateInteractive(cmd *cobra.Command, opts runOptions) error { - usage := func() { - fmt.Fprintln(os.Stderr, "Available Commands:") - fmt.Fprintln(os.Stderr, " /set Set session variables") - fmt.Fprintln(os.Stderr, " /show Show model information") - fmt.Fprintln(os.Stderr, " /load Load a session or model") - fmt.Fprintln(os.Stderr, " /save Save your current session") - fmt.Fprintln(os.Stderr, " /clear Clear session context") - fmt.Fprintln(os.Stderr, " /bye Exit") - fmt.Fprintln(os.Stderr, " /?, /help Help for a command") - fmt.Fprintln(os.Stderr, " /? shortcuts Help for keyboard shortcuts") - fmt.Fprintln(os.Stderr, "") - fmt.Fprintln(os.Stderr, "Use \"\"\" to begin a multi-line message.") - - if opts.MultiModal { - fmt.Fprintf(os.Stderr, "Use %s to include .jpg or .png images.\n", filepath.FromSlash("/path/to/file")) - } - - fmt.Fprintln(os.Stderr, "") - } - - usageSet := func() { - fmt.Fprintln(os.Stderr, "Available Commands:") - fmt.Fprintln(os.Stderr, " /set parameter ... Set a parameter") - fmt.Fprintln(os.Stderr, " /set system Set system message") - fmt.Fprintln(os.Stderr, " /set history Enable history") - fmt.Fprintln(os.Stderr, " /set nohistory Disable history") - fmt.Fprintln(os.Stderr, " /set wordwrap Enable wordwrap") - fmt.Fprintln(os.Stderr, " /set nowordwrap Disable wordwrap") - fmt.Fprintln(os.Stderr, " /set format json Enable JSON mode") - fmt.Fprintln(os.Stderr, " /set noformat Disable formatting") - fmt.Fprintln(os.Stderr, " /set verbose Show LLM stats") - fmt.Fprintln(os.Stderr, " /set quiet Disable LLM stats") - fmt.Fprintln(os.Stderr, "") - } - - usageShortcuts := func() { - fmt.Fprintln(os.Stderr, "Available keyboard shortcuts:") - fmt.Fprintln(os.Stderr, " Ctrl + a Move to the beginning of the line (Home)") - fmt.Fprintln(os.Stderr, " Ctrl + e Move to the end of the line (End)") - fmt.Fprintln(os.Stderr, " Alt + b Move back (left) one word") - fmt.Fprintln(os.Stderr, " Alt + f Move forward (right) one word") - fmt.Fprintln(os.Stderr, " Ctrl + k Delete the sentence after the cursor") - fmt.Fprintln(os.Stderr, " Ctrl + u Delete the sentence before the cursor") - fmt.Fprintln(os.Stderr, " Ctrl + w Delete the word before the cursor") - fmt.Fprintln(os.Stderr, "") - fmt.Fprintln(os.Stderr, " Ctrl + l Clear the screen") - fmt.Fprintln(os.Stderr, " Ctrl + c Stop the model from responding") - fmt.Fprintln(os.Stderr, " Ctrl + d Exit ollama (/bye)") - fmt.Fprintln(os.Stderr, "") - } - - usageShow := func() { - fmt.Fprintln(os.Stderr, "Available Commands:") - fmt.Fprintln(os.Stderr, " /show info Show details for this model") - fmt.Fprintln(os.Stderr, " /show license Show model license") - fmt.Fprintln(os.Stderr, " /show modelfile Show Modelfile for this model") - fmt.Fprintln(os.Stderr, " /show parameters Show parameters for this model") - fmt.Fprintln(os.Stderr, " /show system Show system message") - fmt.Fprintln(os.Stderr, " /show template Show prompt template") - fmt.Fprintln(os.Stderr, "") - } - - // only list out the most common parameters - usageParameters := func() { - fmt.Fprintln(os.Stderr, "Available Parameters:") - fmt.Fprintln(os.Stderr, " /set parameter seed Random number seed") - fmt.Fprintln(os.Stderr, " /set parameter num_predict Max number of tokens to predict") - fmt.Fprintln(os.Stderr, " /set parameter top_k Pick from top k num of tokens") - fmt.Fprintln(os.Stderr, " /set parameter top_p Pick token based on sum of probabilities") - fmt.Fprintln(os.Stderr, " /set parameter min_p Pick token based on top token probability * min_p") - fmt.Fprintln(os.Stderr, " /set parameter num_ctx Set the context size") - fmt.Fprintln(os.Stderr, " /set parameter temperature Set creativity level") - fmt.Fprintln(os.Stderr, " /set parameter repeat_penalty How strongly to penalize repetitions") - fmt.Fprintln(os.Stderr, " /set parameter repeat_last_n Set how far back to look for repetitions") - fmt.Fprintln(os.Stderr, " /set parameter num_gpu The number of layers to send to the GPU") - fmt.Fprintln(os.Stderr, " /set parameter stop ... Set the stop parameters") - fmt.Fprintln(os.Stderr, "") - } - - scanner, err := readline.New(readline.Prompt{ - Prompt: ">>> ", - AltPrompt: "... ", - Placeholder: "Send a message (/? for help)", - AltPlaceholder: `Use """ to end multi-line input`, - }) - if err != nil { - return err - } - - if envconfig.NoHistory() { - scanner.HistoryDisable() - } - - fmt.Print(readline.StartBracketedPaste) - defer fmt.Printf(readline.EndBracketedPaste) - - var sb strings.Builder - var multiline MultilineState - - for { - line, err := scanner.Readline() - switch { - case errors.Is(err, io.EOF): - fmt.Println() - return nil - case errors.Is(err, readline.ErrInterrupt): - if line == "" { - fmt.Println("\nUse Ctrl + d or /bye to exit.") - } - - scanner.Prompt.UseAlt = false - sb.Reset() - - continue - case err != nil: - return err - } - - switch { - case multiline != MultilineNone: - // check if there's a multiline terminating string - before, ok := strings.CutSuffix(line, `"""`) - sb.WriteString(before) - if !ok { - fmt.Fprintln(&sb) - continue - } - - switch multiline { - case MultilineSystem: - opts.System = sb.String() - opts.Messages = append(opts.Messages, api.Message{Role: "system", Content: opts.System}) - fmt.Println("Set system message.") - sb.Reset() - } - - multiline = MultilineNone - scanner.Prompt.UseAlt = false - case strings.HasPrefix(line, `"""`): - line := strings.TrimPrefix(line, `"""`) - line, ok := strings.CutSuffix(line, `"""`) - sb.WriteString(line) - if !ok { - // no multiline terminating string; need more input - fmt.Fprintln(&sb) - multiline = MultilinePrompt - scanner.Prompt.UseAlt = true - } - case scanner.Pasting: - fmt.Fprintln(&sb, line) - continue - case strings.HasPrefix(line, "/list"): - args := strings.Fields(line) - if err := ListHandler(cmd, args[1:]); err != nil { - return err - } - case strings.HasPrefix(line, "/load"): - args := strings.Fields(line) - if len(args) != 2 { - fmt.Println("Usage:\n /load ") - continue - } - opts.Model = args[1] - opts.Messages = []api.Message{} - fmt.Printf("Loading model '%s'\n", opts.Model) - if err := loadModel(cmd, &opts); err != nil { - return err - } - continue - case strings.HasPrefix(line, "/save"): - args := strings.Fields(line) - if len(args) != 2 { - fmt.Println("Usage:\n /save ") - continue - } - - client, err := api.ClientFromEnvironment() - if err != nil { - fmt.Println("error: couldn't connect to ollama server") - return err - } - - req := &api.CreateRequest{ - Name: args[1], - Modelfile: buildModelfile(opts), - } - fn := func(resp api.ProgressResponse) error { return nil } - err = client.Create(cmd.Context(), req, fn) - if err != nil { - if strings.Contains(err.Error(), errtypes.InvalidModelNameErrMsg) { - fmt.Printf("error: The model name '%s' is invalid\n", args[1]) - continue - } - return err - } - fmt.Printf("Created new model '%s'\n", args[1]) - continue - case strings.HasPrefix(line, "/clear"): - opts.Messages = []api.Message{} - if opts.System != "" { - newMessage := api.Message{Role: "system", Content: opts.System} - opts.Messages = append(opts.Messages, newMessage) - } - fmt.Println("Cleared session context") - continue - case strings.HasPrefix(line, "/set"): - args := strings.Fields(line) - if len(args) > 1 { - switch args[1] { - case "history": - scanner.HistoryEnable() - case "nohistory": - scanner.HistoryDisable() - case "wordwrap": - opts.WordWrap = true - fmt.Println("Set 'wordwrap' mode.") - case "nowordwrap": - opts.WordWrap = false - fmt.Println("Set 'nowordwrap' mode.") - case "verbose": - if err := cmd.Flags().Set("verbose", "true"); err != nil { - return err - } - fmt.Println("Set 'verbose' mode.") - case "quiet": - if err := cmd.Flags().Set("verbose", "false"); err != nil { - return err - } - fmt.Println("Set 'quiet' mode.") - case "format": - if len(args) < 3 || args[2] != "json" { - fmt.Println("Invalid or missing format. For 'json' mode use '/set format json'") - } else { - opts.Format = args[2] - fmt.Printf("Set format to '%s' mode.\n", args[2]) - } - case "noformat": - opts.Format = "" - fmt.Println("Disabled format.") - case "parameter": - if len(args) < 4 { - usageParameters() - continue - } - params := args[3:] - fp, err := api.FormatParams(map[string][]string{args[2]: params}) - if err != nil { - fmt.Printf("Couldn't set parameter: %q\n", err) - continue - } - fmt.Printf("Set parameter '%s' to '%s'\n", args[2], strings.Join(params, ", ")) - opts.Options[args[2]] = fp[args[2]] - case "system": - if len(args) < 3 { - usageSet() - continue - } - - multiline = MultilineSystem - - line := strings.Join(args[2:], " ") - line, ok := strings.CutPrefix(line, `"""`) - if !ok { - multiline = MultilineNone - } else { - // only cut suffix if the line is multiline - line, ok = strings.CutSuffix(line, `"""`) - if ok { - multiline = MultilineNone - } - } - - sb.WriteString(line) - if multiline != MultilineNone { - scanner.Prompt.UseAlt = true - continue - } - - opts.System = sb.String() // for display in modelfile - newMessage := api.Message{Role: "system", Content: sb.String()} - // Check if the slice is not empty and the last message is from 'system' - if len(opts.Messages) > 0 && opts.Messages[len(opts.Messages)-1].Role == "system" { - // Replace the last message - opts.Messages[len(opts.Messages)-1] = newMessage - } else { - opts.Messages = append(opts.Messages, newMessage) - } - fmt.Println("Set system message.") - sb.Reset() - - sb.Reset() - continue - default: - fmt.Printf("Unknown command '/set %s'. Type /? for help\n", args[1]) - } - } else { - usageSet() - } - case strings.HasPrefix(line, "/show"): - args := strings.Fields(line) - if len(args) > 1 { - client, err := api.ClientFromEnvironment() - if err != nil { - fmt.Println("error: couldn't connect to ollama server") - return err - } - req := &api.ShowRequest{ - Name: opts.Model, - System: opts.System, - Options: opts.Options, - } - resp, err := client.Show(cmd.Context(), req) - if err != nil { - fmt.Println("error: couldn't get model") - return err - } - - switch args[1] { - case "info": - showInfo(resp) - case "license": - if resp.License == "" { - fmt.Println("No license was specified for this model.") - } else { - fmt.Println(resp.License) - } - case "modelfile": - fmt.Println(resp.Modelfile) - case "parameters": - if resp.Parameters == "" { - fmt.Println("No parameters were specified for this model.") - } else { - if len(opts.Options) > 0 { - fmt.Println("User defined parameters:") - for k, v := range opts.Options { - fmt.Printf("%-*s %v\n", 30, k, v) - } - fmt.Println() - } - fmt.Println("Model defined parameters:") - fmt.Println(resp.Parameters) - } - case "system": - switch { - case opts.System != "": - fmt.Println(opts.System + "\n") - case resp.System != "": - fmt.Println(resp.System + "\n") - default: - fmt.Println("No system message was specified for this model.") - } - case "template": - if resp.Template != "" { - fmt.Println(resp.Template) - } else { - fmt.Println("No prompt template was specified for this model.") - } - default: - fmt.Printf("Unknown command '/show %s'. Type /? for help\n", args[1]) - } - } else { - usageShow() - } - case strings.HasPrefix(line, "/help"), strings.HasPrefix(line, "/?"): - args := strings.Fields(line) - if len(args) > 1 { - switch args[1] { - case "set", "/set": - usageSet() - case "show", "/show": - usageShow() - case "shortcut", "shortcuts": - usageShortcuts() - } - } else { - usage() - } - case strings.HasPrefix(line, "/exit"), strings.HasPrefix(line, "/bye"): - return nil - case strings.HasPrefix(line, "/"): - args := strings.Fields(line) - isFile := false - - if opts.MultiModal { - for _, f := range extractFileNames(line) { - if strings.HasPrefix(f, args[0]) { - isFile = true - break - } - } - } - - if !isFile { - fmt.Printf("Unknown command '%s'. Type /? for help\n", args[0]) - continue - } - - sb.WriteString(line) - default: - sb.WriteString(line) - } - - if sb.Len() > 0 && multiline == MultilineNone { - newMessage := api.Message{Role: "user", Content: sb.String()} - - if opts.MultiModal { - msg, images, err := extractFileData(sb.String()) - if err != nil { - return err - } - - // clear all previous images for better responses - if len(images) > 0 { - for i := range opts.Messages { - opts.Messages[i].Images = nil - } - } - - newMessage.Content = msg - newMessage.Images = images - } - - opts.Messages = append(opts.Messages, newMessage) - - assistant, err := chat(cmd, opts) - if err != nil { - return err - } - if assistant != nil { - opts.Messages = append(opts.Messages, *assistant) - } - - sb.Reset() - } - } -} - -func buildModelfile(opts runOptions) string { - var f parser.File - f.Commands = append(f.Commands, parser.Command{Name: "model", Args: cmp.Or(opts.ParentModel, opts.Model)}) - - if opts.System != "" { - f.Commands = append(f.Commands, parser.Command{Name: "system", Args: opts.System}) - } - - keys := maps.Keys(opts.Options) - slices.Sort(keys) - for _, k := range keys { - v := opts.Options[k] - var cmds []parser.Command - switch t := v.(type) { - case []string: - for _, s := range t { - cmds = append(cmds, parser.Command{Name: k, Args: s}) - } - default: - cmds = append(cmds, parser.Command{Name: k, Args: fmt.Sprintf("%v", t)}) - } - - f.Commands = append(f.Commands, cmds...) - } - - for _, msg := range opts.Messages { - f.Commands = append(f.Commands, parser.Command{Name: "message", Args: fmt.Sprintf("%s: %s", msg.Role, msg.Content)}) - } - - return f.String() -} - -func normalizeFilePath(fp string) string { - // Define a map of escaped characters and their replacements - replacements := map[string]string{ - "\\ ": " ", // Escaped space - "\\(": "(", // Escaped left parenthesis - "\\)": ")", // Escaped right parenthesis - "\\[": "[", // Escaped left square bracket - "\\]": "]", // Escaped right square bracket - "\\{": "{", // Escaped left curly brace - "\\}": "}", // Escaped right curly brace - "\\$": "$", // Escaped dollar sign - "\\&": "&", // Escaped ampersand - "\\;": ";", // Escaped semicolon - "\\'": "'", // Escaped single quote - "\\\\": "\\", // Escaped backslash - "\\*": "*", // Escaped asterisk - "\\?": "?", // Escaped question mark - } - - for escaped, actual := range replacements { - fp = strings.ReplaceAll(fp, escaped, actual) - } - return fp -} - -func extractFileNames(input string) []string { - // Regex to match file paths starting with optional drive letter, / ./ \ or .\ and include escaped or unescaped spaces (\ or %20) - // and followed by more characters and a file extension - // This will capture non filename strings, but we'll check for file existence to remove mismatches - regexPattern := `(?:[a-zA-Z]:)?(?:\./|/|\\)[\S\\ ]+?\.(?i:jpg|jpeg|png|svg)\b` - re := regexp.MustCompile(regexPattern) - - return re.FindAllString(input, -1) -} - -func extractFileData(input string) (string, []api.ImageData, error) { - filePaths := extractFileNames(input) - var imgs []api.ImageData - - for _, fp := range filePaths { - nfp := normalizeFilePath(fp) - data, err := getImageData(nfp) - if err != nil { - if os.IsNotExist(err) { - continue - } - fmt.Fprintf(os.Stderr, "Couldn't process image: %q\n", err) - return "", imgs, err - } - fmt.Fprintf(os.Stderr, "Added image '%s'\n", nfp) - input = strings.ReplaceAll(input, fp, "") - imgs = append(imgs, data) - } - return input, imgs, nil -} - -func getImageData(filePath string) ([]byte, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, err - } - defer file.Close() - - buf := make([]byte, 512) - _, err = file.Read(buf) - if err != nil { - return nil, err - } - - contentType := http.DetectContentType(buf) - allowedTypes := []string{"image/jpeg", "image/jpg", "image/png"} - if !slices.Contains(allowedTypes, contentType) { - return nil, fmt.Errorf("invalid image type: %s", contentType) - } - - info, err := file.Stat() - if err != nil { - return nil, err - } - - // Check if the file size exceeds 100MB - var maxSize int64 = 100 * 1024 * 1024 // 100MB in bytes - if info.Size() > maxSize { - return nil, errors.New("file size exceeds maximum limit (100MB)") - } - - buf = make([]byte, info.Size()) - _, err = file.Seek(0, 0) - if err != nil { - return nil, err - } - - _, err = io.ReadFull(file, buf) - if err != nil { - return nil, err - } - - return buf, nil -} diff --git a/ollama/cmd/interactive_test.go b/ollama/cmd/interactive_test.go deleted file mode 100755 index bb7e0ab..0000000 --- a/ollama/cmd/interactive_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package cmd - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/assert" - - "github.com/ollama/ollama/api" -) - -func TestExtractFilenames(t *testing.T) { - // Unix style paths - input := ` some preamble - ./relative\ path/one.png inbetween1 ./not a valid two.jpg inbetween2 -/unescaped space /three.jpeg inbetween3 /valid\ path/dir/four.png "./quoted with spaces/five.svg` - res := extractFileNames(input) - assert.Len(t, res, 5) - assert.Contains(t, res[0], "one.png") - assert.Contains(t, res[1], "two.jpg") - assert.Contains(t, res[2], "three.jpeg") - assert.Contains(t, res[3], "four.png") - assert.Contains(t, res[4], "five.svg") - assert.NotContains(t, res[4], '"') - assert.NotContains(t, res, "inbtween") - - // Windows style paths - input = ` some preamble - c:/users/jdoe/one.png inbetween1 c:/program files/someplace/two.jpg inbetween2 - /absolute/nospace/three.jpeg inbetween3 /absolute/with space/four.png inbetween4 -./relative\ path/five.svg inbetween5 "./relative with/spaces/six.png inbetween6 -d:\path with\spaces\seven.svg inbetween7 c:\users\jdoe\eight.png inbetween8 - d:\program files\someplace\nine.png inbetween9 "E:\program files\someplace\ten.svg some ending -` - res = extractFileNames(input) - assert.Len(t, res, 10) - assert.NotContains(t, res, "inbtween") - assert.Contains(t, res[0], "one.png") - assert.Contains(t, res[0], "c:") - assert.Contains(t, res[1], "two.jpg") - assert.Contains(t, res[1], "c:") - assert.Contains(t, res[2], "three.jpeg") - assert.Contains(t, res[3], "four.png") - assert.Contains(t, res[4], "five.svg") - assert.Contains(t, res[5], "six.png") - assert.Contains(t, res[6], "seven.svg") - assert.Contains(t, res[6], "d:") - assert.Contains(t, res[7], "eight.png") - assert.Contains(t, res[7], "c:") - assert.Contains(t, res[8], "nine.png") - assert.Contains(t, res[8], "d:") - assert.Contains(t, res[9], "ten.svg") - assert.Contains(t, res[9], "E:") -} - -func TestModelfileBuilder(t *testing.T) { - opts := runOptions{ - Model: "hork", - System: "You are part horse and part shark, but all hork. Do horklike things", - Messages: []api.Message{ - {Role: "user", Content: "Hey there hork!"}, - {Role: "assistant", Content: "Yes it is true, I am half horse, half shark."}, - }, - Options: map[string]any{ - "temperature": 0.9, - "seed": 42, - "penalize_newline": false, - "stop": []string{"hi", "there"}, - }, - } - - t.Run("model", func(t *testing.T) { - expect := `FROM hork -SYSTEM You are part horse and part shark, but all hork. Do horklike things -PARAMETER penalize_newline false -PARAMETER seed 42 -PARAMETER stop hi -PARAMETER stop there -PARAMETER temperature 0.9 -MESSAGE user Hey there hork! -MESSAGE assistant Yes it is true, I am half horse, half shark. -` - - actual := buildModelfile(opts) - if diff := cmp.Diff(expect, actual); diff != "" { - t.Errorf("mismatch (-want +got):\n%s", diff) - } - }) - - t.Run("parent model", func(t *testing.T) { - opts.ParentModel = "horseshark" - expect := `FROM horseshark -SYSTEM You are part horse and part shark, but all hork. Do horklike things -PARAMETER penalize_newline false -PARAMETER seed 42 -PARAMETER stop hi -PARAMETER stop there -PARAMETER temperature 0.9 -MESSAGE user Hey there hork! -MESSAGE assistant Yes it is true, I am half horse, half shark. -` - actual := buildModelfile(opts) - if diff := cmp.Diff(expect, actual); diff != "" { - t.Errorf("mismatch (-want +got):\n%s", diff) - } - }) -} diff --git a/ollama/cmd/start.go b/ollama/cmd/start.go deleted file mode 100755 index 0c4eed0..0000000 --- a/ollama/cmd/start.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build darwin || windows - -package cmd - -import ( - "context" - "errors" - "time" - - "github.com/ollama/ollama/api" -) - -func waitForServer(ctx context.Context, client *api.Client) error { - // wait for the server to start - timeout := time.After(5 * time.Second) - tick := time.Tick(500 * time.Millisecond) - for { - select { - case <-timeout: - return errors.New("timed out waiting for server to start") - case <-tick: - if err := client.Heartbeat(ctx); err == nil { - return nil // server has started - } - } - } -} diff --git a/ollama/cmd/start_darwin.go b/ollama/cmd/start_darwin.go deleted file mode 100755 index 1a9a1ae..0000000 --- a/ollama/cmd/start_darwin.go +++ /dev/null @@ -1,30 +0,0 @@ -package cmd - -import ( - "context" - "errors" - "os" - "os/exec" - "strings" - - "github.com/ollama/ollama/api" -) - -func startApp(ctx context.Context, client *api.Client) error { - exe, err := os.Executable() - if err != nil { - return err - } - link, err := os.Readlink(exe) - if err != nil { - return err - } - if !strings.Contains(link, "Ollama.app") { - return errors.New("could not find ollama app") - } - path := strings.Split(link, "Ollama.app") - if err := exec.Command("/usr/bin/open", "-a", path[0]+"Ollama.app").Run(); err != nil { - return err - } - return waitForServer(ctx, client) -} diff --git a/ollama/cmd/start_default.go b/ollama/cmd/start_default.go deleted file mode 100755 index 5eabb28..0000000 --- a/ollama/cmd/start_default.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build !windows && !darwin - -package cmd - -import ( - "context" - "errors" - - "github.com/ollama/ollama/api" -) - -func startApp(ctx context.Context, client *api.Client) error { - return errors.New("could not connect to ollama server, run 'ollama serve' to start it") -} diff --git a/ollama/cmd/start_windows.go b/ollama/cmd/start_windows.go deleted file mode 100755 index 5bca243..0000000 --- a/ollama/cmd/start_windows.go +++ /dev/null @@ -1,58 +0,0 @@ -package cmd - -import ( - "context" - "errors" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "syscall" - - "github.com/ollama/ollama/api" -) - -func startApp(ctx context.Context, client *api.Client) error { - // log.Printf("XXX Attempting to find and start ollama app") - AppName := "ollama app.exe" - exe, err := os.Executable() - if err != nil { - return err - } - appExe := filepath.Join(filepath.Dir(exe), AppName) - _, err = os.Stat(appExe) - if errors.Is(err, os.ErrNotExist) { - // Try the standard install location - localAppData := os.Getenv("LOCALAPPDATA") - appExe = filepath.Join(localAppData, "Ollama", AppName) - _, err := os.Stat(appExe) - if errors.Is(err, os.ErrNotExist) { - // Finally look in the path - appExe, err = exec.LookPath(AppName) - if err != nil { - return errors.New("could not locate ollama app") - } - } - } - // log.Printf("XXX attempting to start app %s", appExe) - - cmd_path := "c:\\Windows\\system32\\cmd.exe" - cmd := exec.Command(cmd_path, "/c", appExe) - // TODO - these hide flags aren't working - still pops up a command window for some reason - cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 0x08000000, HideWindow: true} - - // TODO this didn't help either... - cmd.Stdin = strings.NewReader("") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Start(); err != nil { - return fmt.Errorf("unable to start ollama app %w", err) - } - - if cmd.Process != nil { - defer cmd.Process.Release() //nolint:errcheck - } - return waitForServer(ctx, client) -} diff --git a/ollama/convert/convert.go b/ollama/convert/convert.go deleted file mode 100755 index b9461e4..0000000 --- a/ollama/convert/convert.go +++ /dev/null @@ -1,122 +0,0 @@ -package convert - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/fs" - "log/slog" - - "github.com/ollama/ollama/llm" -) - -type Parameters struct { - Architectures []string `json:"architectures"` - VocabSize uint32 `json:"vocab_size"` -} - -func (Parameters) KV(t *Tokenizer) llm.KV { - kv := llm.KV{ - "general.file_type": uint32(1), - "general.quantization_version": uint32(2), - "tokenizer.ggml.pre": t.Pre, - "tokenizer.ggml.model": t.Vocabulary.Model, - "tokenizer.ggml.tokens": t.Vocabulary.Tokens, - "tokenizer.ggml.scores": t.Vocabulary.Scores, - "tokenizer.ggml.token_type": t.Vocabulary.Types, - } - - if t.Template != "" { - kv["tokenizer.chat_template"] = t.Template - } - - for _, sv := range t.SpecialVocabulary { - kv[fmt.Sprintf("tokenizer.ggml.%s_token_id", sv.Key())] = uint32(sv.ID) - kv[fmt.Sprintf("tokenizer.ggml.add_%s_token", sv.Key())] = sv.AddToken - } - - return kv -} - -func (Parameters) specialTokenTypes() []string { - return []string{ - "bos", "eos", "unk", "sep", "pad", "cls", "mask", - } -} - -func (Parameters) writeFile(ws io.WriteSeeker, kv llm.KV, ts []llm.Tensor) error { - return llm.WriteGGUF(ws, kv, ts) -} - -type Converter interface { - // KV maps parameters to LLM key-values - KV(*Tokenizer) llm.KV - // Tensors maps input tensors to LLM tensors. Model specific modifications can be done here. - Tensors([]Tensor) []llm.Tensor - - // tensorName returns the LLM tensor name for a specific input name - tensorName(string) string - // specialTokenTypes returns any special token types the model uses - specialTokenTypes() []string - writeFile(io.WriteSeeker, llm.KV, []llm.Tensor) error -} - -// Convert writes an Ollama compatible model to the provided io.WriteSeeker based on configurations -// and files it finds in the input path. -// Supported input model formats include safetensors. -// Supported input tokenizers files include tokenizer.json (preferred) and tokenizer.model. -func Convert(fsys fs.FS, ws io.WriteSeeker) error { - bts, err := fs.ReadFile(fsys, "config.json") - if err != nil { - return err - } - - var p Parameters - if err := json.Unmarshal(bts, &p); err != nil { - return err - } - - if len(p.Architectures) < 1 { - return errors.New("unknown architecture") - } - - var conv Converter - switch p.Architectures[0] { - case "LlamaForCausalLM", "MistralForCausalLM": - conv = &llama{} - case "MixtralForCausalLM": - conv = &mixtral{} - case "GemmaForCausalLM": - conv = &gemma{} - default: - return errors.New("unsupported architecture") - } - - if err := json.Unmarshal(bts, conv); err != nil { - return err - } - - t, err := parseTokenizer(fsys, conv.specialTokenTypes()) - if err != nil { - return err - } - - if vocabSize := int(p.VocabSize); vocabSize > len(t.Vocabulary.Tokens) { - slog.Warn("vocabulary is smaller than expected, padding with dummy tokens", "expect", p.VocabSize, "actual", len(t.Vocabulary.Tokens)) - for i := range vocabSize - len(t.Vocabulary.Tokens) { - t.Vocabulary.Tokens = append(t.Vocabulary.Tokens, fmt.Sprintf("[PAD%d]", i)) - t.Vocabulary.Scores = append(t.Vocabulary.Scores, -1) - t.Vocabulary.Types = append(t.Vocabulary.Types, tokenTypeUserDefined) - } - } else { - slog.Debug("vocabulary", "size", len(t.Vocabulary.Tokens)) - } - - ts, err := parseTensors(fsys) - if err != nil { - return err - } - - return conv.writeFile(ws, conv.KV(t), conv.Tensors(ts)) -} diff --git a/ollama/convert/convert_gemma.go b/ollama/convert/convert_gemma.go deleted file mode 100755 index 9213e15..0000000 --- a/ollama/convert/convert_gemma.go +++ /dev/null @@ -1,103 +0,0 @@ -package convert - -import ( - "strings" - - "github.com/pdevine/tensor" - "github.com/pdevine/tensor/native" - - "github.com/ollama/ollama/llm" -) - -type gemma struct { - Parameters - MaxPositionEmbeddings uint32 `json:"max_position_embeddings"` - HiddenSize uint32 `json:"hidden_size"` - HiddenLayers uint32 `json:"num_hidden_layers"` - IntermediateSize uint32 `json:"intermediate_size"` - NumAttentionHeads uint32 `json:"num_attention_heads"` - NumKeyValueHeads uint32 `json:"num_key_value_heads"` - RMSNormEPS float32 `json:"rms_norm_eps"` - HeadDim uint32 `json:"head_dim"` -} - -var _ Converter = (*gemma)(nil) - -func (p *gemma) KV(t *Tokenizer) llm.KV { - kv := p.Parameters.KV(t) - kv["general.architecture"] = "gemma" - kv["general.name"] = "gemma" - kv["gemma.context_length"] = p.MaxPositionEmbeddings - kv["gemma.embedding_length"] = p.HiddenSize - kv["gemma.block_count"] = p.HiddenLayers - kv["gemma.feed_forward_length"] = p.IntermediateSize - kv["gemma.attention.head_count"] = p.NumAttentionHeads - kv["gemma.attention.head_count_kv"] = p.NumKeyValueHeads - kv["gemma.attention.layer_norm_rms_epsilon"] = p.RMSNormEPS - kv["gemma.attention.key_length"] = p.HeadDim - kv["gemma.attention.value_length"] = p.HeadDim - kv["tokenizer.ggml.eot_token_id"] = uint32(107) - kv["tokenizer.ggml.middle_token_id"] = uint32(68) - kv["tokenizer.ggml.prefix_token_id"] = uint32(67) - kv["tokenizer.ggml.suffix_token_id"] = uint32(69) - return kv -} - -func (p *gemma) Tensors(ts []Tensor) []llm.Tensor { - var out []llm.Tensor - for _, t := range ts { - name := p.tensorName(t.Name()) - if strings.HasSuffix(name, "_norm.weight") { - t.SetRepacker(p.addOne) - } - - out = append(out, llm.Tensor{ - Name: name, - Kind: t.Kind(), - Shape: t.Shape(), - WriterTo: t, - }) - } - - return out -} - -func (p *gemma) tensorName(n string) string { - return strings.NewReplacer( - "model.embed_tokens", "token_embd", - "model.norm", "output_norm", - "model.layers", "blk", - "input_layernorm", "attn_norm", - "self_attn.q_proj", "attn_q", - "self_attn.k_proj", "attn_k", - "self_attn.v_proj", "attn_v", - "self_attn.o_proj", "attn_output", - "mlp.gate_proj", "ffn_gate", - "mlp.down_proj", "ffn_down", - "mlp.up_proj", "ffn_up", - "post_attention_layernorm", "ffn_norm", - "block_sparse_moe.gate", "ffn_inp", - ).Replace(n) -} - -func (*gemma) addOne(_ string, data []float32, shape []uint64) ([]float32, error) { - n := tensor.New(tensor.WithShape(int(shape[0])), tensor.WithBacking(data)) - ones := tensor.Ones(tensor.Float32, int(shape[0])) - - n, err := n.Add(ones) - if err != nil { - return nil, err - } - - ts, err := native.SelectF32(n, 0) - if err != nil { - return nil, err - } - - var f32s []float32 - for _, t := range ts { - f32s = append(f32s, t...) - } - - return f32s, nil -} diff --git a/ollama/convert/convert_llama.go b/ollama/convert/convert_llama.go deleted file mode 100755 index 0383a85..0000000 --- a/ollama/convert/convert_llama.go +++ /dev/null @@ -1,183 +0,0 @@ -package convert - -import ( - "cmp" - "fmt" - "strings" - - "github.com/pdevine/tensor" - "github.com/pdevine/tensor/native" - - "github.com/ollama/ollama/llm" -) - -type llama struct { - Parameters - NLayers uint32 `json:"n_layers"` - NumHiddenLayers uint32 `json:"num_hidden_layers"` - NLayer uint32 `json:"n_layer"` - MaxPositionEmbeddings uint32 `json:"max_position_embeddings"` - NCtx uint32 `json:"n_ctx"` - HiddenSize uint32 `json:"hidden_size"` - NEmbd uint32 `json:"n_embd"` - IntermediateSize uint32 `json:"intermediate_size"` - NInner uint32 `json:"n_inner"` - NumAttentionHeads uint32 `json:"num_attention_heads"` - NHead uint32 `json:"n_head"` - NumKeyValueHeads uint32 `json:"num_key_value_heads"` - RopeTheta float32 `json:"rope_theta"` - RopeScaling struct { - Type string `json:"type"` - Factor float32 `json:"factor"` - } `json:"rope_scaling"` - RMSNormEPS float32 `json:"rms_norm_eps"` - LayerNormEPS float32 `json:"layer_norm_eps"` - LayerNormEpsilon float32 `json:"layer_norm_epsilon"` - NormEpsilon float32 `json:"norm_epsilon"` - HeadDim uint32 `json:"head_dim"` -} - -var _ Converter = (*llama)(nil) - -func (p *llama) KV(t *Tokenizer) llm.KV { - kv := p.Parameters.KV(t) - kv["general.architecture"] = "llama" - kv["general.name"] = "llama" - kv["llama.vocab_size"] = p.VocabSize - - kv["llama.block_count"] = cmp.Or(p.NLayers, p.NumHiddenLayers, p.NLayer) - - if contextLength := cmp.Or(p.MaxPositionEmbeddings, p.NCtx); contextLength > 0 { - kv["llama.context_length"] = contextLength - } - - if embeddingLength := cmp.Or(p.HiddenSize, p.NEmbd); embeddingLength > 0 { - kv["llama.embedding_length"] = cmp.Or(p.HiddenSize, p.NEmbd) - } - - if feedForwardLength := cmp.Or(p.IntermediateSize, p.NInner); feedForwardLength > 0 { - kv["llama.feed_forward_length"] = cmp.Or(p.IntermediateSize, p.NInner) - } - - if headCount := cmp.Or(p.NumAttentionHeads, p.NHead); headCount > 0 { - kv["llama.attention.head_count"] = cmp.Or(p.NumAttentionHeads, p.NHead) - kv["llama.rope.dimension_count"] = p.HiddenSize / headCount - } - - if p.RopeTheta > 0 { - kv["llama.rope.freq_base"] = p.RopeTheta - } - - if p.RopeScaling.Type == "linear" { - kv["llama.rope.scaling.type"] = p.RopeScaling.Type - kv["llama.rope.scaling.factor"] = p.RopeScaling.Factor - } - - if p.NumKeyValueHeads > 0 { - kv["llama.attention.head_count_kv"] = p.NumKeyValueHeads - } - - if p.RMSNormEPS > 0 { - kv["llama.attention.layer_norm_rms_epsilon"] = p.RMSNormEPS - } - - if layerNormEpsilon := cmp.Or(p.LayerNormEPS, p.LayerNormEpsilon, p.NormEpsilon); layerNormEpsilon > 0 { - kv["llama.attention.layer_norm_epsilon"] = layerNormEpsilon - } - - if p.HeadDim > 0 { - kv["llama.attention.key_length"] = p.HeadDim - kv["llama.attention.value_length"] = p.HeadDim - } - - if len(t.Merges) > 0 { - kv["tokenizer.ggml.merges"] = t.Merges - } - - return kv -} - -func (p *llama) Tensors(ts []Tensor) []llm.Tensor { - var out []llm.Tensor - for _, t := range ts { - name := p.tensorName(t.Name()) - if strings.HasSuffix(name, "attn_q.weight") || - strings.HasSuffix(name, "attn_k.weight") { - t.SetRepacker(p.repack) - } - - out = append(out, llm.Tensor{ - Name: name, - Kind: t.Kind(), - Shape: t.Shape(), - WriterTo: t, - }) - } - - return out -} - -func (p *llama) tensorName(n string) string { - return strings.NewReplacer( - "lm_head", "output", - "model.embed_tokens", "token_embd", - "model.norm", "output_norm", - "model.layers", "blk", - "input_layernorm", "attn_norm", - "self_attn.q_proj", "attn_q", - "self_attn.k_proj", "attn_k", - "self_attn.v_proj", "attn_v", - "self_attn.o_proj", "attn_output", - "mlp.gate_proj", "ffn_gate", - "mlp.down_proj", "ffn_down", - "mlp.up_proj", "ffn_up", - "post_attention_layernorm", "ffn_norm", - // mixtral - "block_sparse_moe.gate", "ffn_gate_inp", - ).Replace(n) -} - -func (p *llama) repack(name string, data []float32, shape []uint64) ([]float32, error) { - var dims []int - for _, dim := range shape { - dims = append(dims, int(dim)) - } - - var heads uint32 - if strings.HasSuffix(name, "q_proj.weight") { - heads = p.NumAttentionHeads - } else if strings.HasSuffix(name, "k_proj.weight") { - heads = cmp.Or(p.NumKeyValueHeads, p.NumAttentionHeads) - } else { - return nil, fmt.Errorf("unknown tensor for repack: %s", name) - } - - n := tensor.New(tensor.WithShape(dims...), tensor.WithBacking(data)) - if err := n.Reshape(append([]int{int(heads), 2, dims[0] / int(heads) / 2}, dims[1:]...)...); err != nil { - return nil, err - } - - if err := n.T(0, 2, 1, 3); err != nil { - return nil, err - } - - if err := n.Reshape(dims...); err != nil { - return nil, err - } - - if err := n.Transpose(); err != nil { - return nil, err - } - - ts, err := native.SelectF32(n, 1) - if err != nil { - return nil, err - } - - var f32s []float32 - for _, t := range ts { - f32s = append(f32s, t...) - } - - return f32s, nil -} diff --git a/ollama/convert/convert_mixtral.go b/ollama/convert/convert_mixtral.go deleted file mode 100755 index 3263a27..0000000 --- a/ollama/convert/convert_mixtral.go +++ /dev/null @@ -1,89 +0,0 @@ -package convert - -import ( - "fmt" - "io" - "slices" - "strings" - - "github.com/ollama/ollama/llm" -) - -type mixtral struct { - llama - NumLocalExperts uint32 `json:"num_local_experts"` - NumExpertsPerToken uint32 `json:"num_experts_per_tok"` -} - -var _ Converter = (*mixtral)(nil) - -func (p *mixtral) KV(t *Tokenizer) llm.KV { - kv := p.llama.KV(t) - - if p.NumLocalExperts > 0 { - kv["llama.expert_count"] = p.NumLocalExperts - } - - if p.NumExpertsPerToken > 0 { - kv["llama.expert_used_count"] = p.NumExpertsPerToken - } - - return kv -} - -func (p *mixtral) Tensors(ts []Tensor) []llm.Tensor { - oldnew := []string{ - "model.layers", "blk", - "w1", "ffn_gate_exps", - "w2", "ffn_down_exps", - "w3", "ffn_up_exps", - } - - for i := range p.NumLocalExperts { - oldnew = append(oldnew, fmt.Sprintf(".block_sparse_moe.experts.%d.", i), ".") - } - - // group experts of the same layer (model.layers.%d) and type (w[123]) into a single tensor - namer := strings.NewReplacer(oldnew...) - experts := make(map[string]experts) - - // merge experts into a single tensor while removing them from ts - ts = slices.DeleteFunc(ts, func(t Tensor) bool { - if !strings.Contains(t.Name(), ".block_sparse_moe.experts.") { - return false - } - - name := namer.Replace(t.Name()) - experts[name] = append(experts[name], t) - return true - }) - - var out []llm.Tensor - for n, e := range experts { - // TODO(mxyng): sanity check experts - out = append(out, llm.Tensor{ - Name: n, - Kind: e[0].Kind(), - Shape: append([]uint64{uint64(len(e))}, e[0].Shape()...), - WriterTo: e, - }) - } - - return append(out, p.llama.Tensors(ts)...) -} - -type experts []Tensor - -func (e experts) WriteTo(w io.Writer) (int64, error) { - // TODO(mxyng): experts _should_ be numerically sorted by expert but this should check - for _, t := range e { - // the canonical merged experts tensor stacks all experts along a new, 0 axis, - // e.g. `tensor.Stack(0, e[0], e[1:]...)`, which requires allocating temporary buffers - // this accomplishes the same thing by writing each expert tensor in sequence - if _, err := t.WriteTo(w); err != nil { - return 0, err - } - } - - return 0, nil -} diff --git a/ollama/convert/convert_test.go b/ollama/convert/convert_test.go deleted file mode 100755 index 88f3849..0000000 --- a/ollama/convert/convert_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package convert - -import ( - "crypto/sha256" - "encoding/hex" - "encoding/json" - "flag" - "fmt" - "io" - "io/fs" - "log/slog" - "math" - "os" - "path/filepath" - "slices" - "testing" - - "golang.org/x/exp/maps" - - "github.com/ollama/ollama/llm" -) - -func convertFull(t *testing.T, fsys fs.FS) (*os.File, llm.KV, llm.Tensors) { - t.Helper() - - f, err := os.CreateTemp(t.TempDir(), "f16") - if err != nil { - t.Fatal(err) - } - defer f.Close() - - if err := Convert(fsys, f); err != nil { - t.Fatal(err) - } - - r, err := os.Open(f.Name()) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { r.Close() }) - - m, _, err := llm.DecodeGGML(r, math.MaxInt) - if err != nil { - t.Fatal(err) - } - - if _, err := r.Seek(0, io.SeekStart); err != nil { - t.Fatal(err) - } - - return r, m.KV(), m.Tensors() -} - -func TestMain(m *testing.M) { - var level slog.Level - flag.TextVar(&level, "level", slog.LevelInfo, "log level") - flag.Parse() - slog.SetLogLoggerLevel(level) - os.Exit(m.Run()) -} - -func TestConvertFull(t *testing.T) { - cases := []string{ - "Meta-Llama-3-8B-Instruct", - "Mistral-7B-Instruct-v0.2", - "Mixtral-8x7B-Instruct-v0.1", - "gemma-2b-it", - } - - for i := range cases { - tt := cases[i] - t.Run(tt, func(t *testing.T) { - t.Parallel() - - p := filepath.Join("testdata", tt) - if testing.Short() { - t.Skip("skipping in short mode") - } else if _, err := os.Stat(p); err != nil { - t.Skipf("%s not found", p) - } - - f, kv, tensors := convertFull(t, os.DirFS(p)) - actual := make(map[string]string) - for k, v := range kv { - if s, ok := v.(json.Marshaler); !ok { - actual[k] = fmt.Sprintf("%v", v) - } else { - bts, err := json.Marshal(s) - if err != nil { - t.Fatal(err) - } - - actual[k] = fmt.Sprintf("%x", sha256.Sum256(bts)) - } - } - - for _, tensor := range tensors.Items { - sha256sum := sha256.New() - sr := io.NewSectionReader(f, int64(tensors.Offset+tensor.Offset), int64(tensor.Size())) - if _, err := io.Copy(sha256sum, sr); err != nil { - t.Fatal(err) - } - - actual[tensor.Name] = hex.EncodeToString(sha256sum.Sum(nil)) - } - - expectFile, err := os.Open(filepath.Join("testdata", fmt.Sprintf("%s.json", tt))) - if err != nil { - t.Fatal(err) - } - - var expect map[string]string - if err := json.NewDecoder(expectFile).Decode(&expect); err != nil { - t.Fatal(err) - } - - keys := maps.Keys(expect) - slices.Sort(keys) - for _, k := range keys { - if v, ok := actual[k]; !ok { - t.Errorf("missing %s", k) - } else if v != expect[k] { - t.Errorf("unexpected %s: want %s, got %s", k, expect[k], v) - } - } - }) - } -} diff --git a/ollama/convert/fs.go b/ollama/convert/fs.go deleted file mode 100755 index 31132db..0000000 --- a/ollama/convert/fs.go +++ /dev/null @@ -1,58 +0,0 @@ -package convert - -import ( - "archive/zip" - "errors" - "io" - "io/fs" - "os" - "path/filepath" -) - -type ZipReader struct { - r *zip.Reader - p string - - // limit is the maximum size of a file that can be read directly - // from the zip archive. Files larger than this size will be extracted - limit int64 -} - -func NewZipReader(r *zip.Reader, p string, limit int64) fs.FS { - return &ZipReader{r, p, limit} -} - -func (z *ZipReader) Open(name string) (fs.File, error) { - r, err := z.r.Open(name) - if err != nil { - return nil, err - } - defer r.Close() - - if fi, err := r.Stat(); err != nil { - return nil, err - } else if fi.Size() < z.limit { - return r, nil - } - - if !filepath.IsLocal(name) { - return nil, zip.ErrInsecurePath - } - - n := filepath.Join(z.p, name) - if _, err := os.Stat(n); errors.Is(err, os.ErrNotExist) { - w, err := os.Create(n) - if err != nil { - return nil, err - } - defer w.Close() - - if _, err := io.Copy(w, r); err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - - return os.Open(n) -} diff --git a/ollama/convert/reader.go b/ollama/convert/reader.go deleted file mode 100755 index ce95208..0000000 --- a/ollama/convert/reader.go +++ /dev/null @@ -1,82 +0,0 @@ -package convert - -import ( - "errors" - "io" - "io/fs" - "strings" -) - -type Tensor interface { - Name() string - Shape() []uint64 - Kind() uint32 - SetRepacker(repacker) - WriteTo(io.Writer) (int64, error) -} - -type tensorBase struct { - name string - shape []uint64 - repacker -} - -func (t tensorBase) Name() string { - return t.name -} - -func (t tensorBase) Shape() []uint64 { - return t.shape -} - -const ( - tensorKindF32 uint32 = iota - tensorKindF16 -) - -func (t tensorBase) Kind() uint32 { - if strings.HasSuffix(t.name, ".block_sparse_moe.gate.weight") { - return 0 - } - - switch len(t.shape) { - case 0: - panic("invalid tensor shape") - case 1: - return tensorKindF32 - default: - return tensorKindF16 - } -} - -func (t *tensorBase) SetRepacker(fn repacker) { - t.repacker = fn -} - -type repacker func(string, []float32, []uint64) ([]float32, error) - -func parseTensors(fsys fs.FS) ([]Tensor, error) { - patterns := []struct { - Pattern string - Func func(fs.FS, ...string) ([]Tensor, error) - }{ - {"model-*-of-*.safetensors", parseSafetensors}, - {"model.safetensors", parseSafetensors}, - {"pytorch_model-*-of-*.bin", parseTorch}, - {"pytorch_model.bin", parseTorch}, - {"consolidated.*.pth", parseTorch}, - } - - for _, pattern := range patterns { - matches, err := fs.Glob(fsys, pattern.Pattern) - if err != nil { - return nil, err - } - - if len(matches) > 0 { - return pattern.Func(fsys, matches...) - } - } - - return nil, errors.New("unknown tensor format") -} diff --git a/ollama/convert/reader_safetensors.go b/ollama/convert/reader_safetensors.go deleted file mode 100755 index 42f902a..0000000 --- a/ollama/convert/reader_safetensors.go +++ /dev/null @@ -1,150 +0,0 @@ -package convert - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "fmt" - "io" - "io/fs" - "slices" - - "github.com/d4l3k/go-bfloat16" - "github.com/x448/float16" - "golang.org/x/exp/maps" -) - -type safetensorMetadata struct { - Type string `json:"dtype"` - Shape []uint64 `json:"shape"` - Offsets []int64 `json:"data_offsets"` -} - -func parseSafetensors(fsys fs.FS, ps ...string) ([]Tensor, error) { - var ts []Tensor - for _, p := range ps { - f, err := fsys.Open(p) - if err != nil { - return nil, err - } - defer f.Close() - - var n int64 - if err := binary.Read(f, binary.LittleEndian, &n); err != nil { - return nil, err - } - - b := bytes.NewBuffer(make([]byte, 0, n)) - if _, err = io.CopyN(b, f, n); err != nil { - return nil, err - } - - var headers map[string]safetensorMetadata - if err := json.NewDecoder(b).Decode(&headers); err != nil { - return nil, err - } - - keys := maps.Keys(headers) - slices.Sort(keys) - - for _, key := range keys { - if value := headers[key]; value.Type != "" { - ts = append(ts, safetensor{ - fs: fsys, - path: p, - dtype: value.Type, - offset: safetensorsPad(n, value.Offsets[0]), - size: safetensorsPad(n, value.Offsets[1]) - safetensorsPad(n, value.Offsets[0]), - tensorBase: &tensorBase{ - name: key, - shape: value.Shape, - }, - }) - } - } - } - - return ts, nil -} - -// safetensorsPad returns the padded size of the safetensors file given a length n and offset s -func safetensorsPad(n, offset int64) int64 { - return 8 + n + offset -} - -type safetensor struct { - fs fs.FS - path string - dtype string - offset int64 - size int64 - *tensorBase -} - -func (st safetensor) WriteTo(w io.Writer) (int64, error) { - f, err := st.fs.Open(st.path) - if err != nil { - return 0, err - } - defer f.Close() - - if seeker, ok := f.(io.Seeker); ok { - if _, err := seeker.Seek(st.offset, io.SeekStart); err != nil { - return 0, err - } - } else { - if _, err := io.CopyN(io.Discard, f, st.offset); err != nil { - return 0, err - } - } - - var f32s []float32 - switch st.dtype { - case "F32": - f32s = make([]float32, st.size/4) - if err = binary.Read(f, binary.LittleEndian, f32s); err != nil { - return 0, err - } - case "F16": - u16s := make([]uint16, st.size/2) - if err = binary.Read(f, binary.LittleEndian, u16s); err != nil { - return 0, err - } - - f32s = make([]float32, len(u16s)) - for i := range u16s { - f32s[i] = float16.Frombits(u16s[i]).Float32() - } - - case "BF16": - u8s := make([]uint8, st.size) - if err = binary.Read(f, binary.LittleEndian, u8s); err != nil { - return 0, err - } - - f32s = bfloat16.DecodeFloat32(u8s) - default: - return 0, fmt.Errorf("unknown data type: %s", st.dtype) - } - - if st.repacker != nil { - f32s, err = st.repacker(st.Name(), f32s, st.Shape()) - if err != nil { - return 0, err - } - } - - switch st.Kind() { - case tensorKindF32: - return 0, binary.Write(w, binary.LittleEndian, f32s) - case tensorKindF16: - f16s := make([]uint16, len(f32s)) - for i := range f32s { - f16s[i] = float16.Fromfloat32(f32s[i]).Bits() - } - - return 0, binary.Write(w, binary.LittleEndian, f16s) - default: - return 0, fmt.Errorf("unknown storage type: %d", st.Kind()) - } -} diff --git a/ollama/convert/reader_torch.go b/ollama/convert/reader_torch.go deleted file mode 100755 index 531996b..0000000 --- a/ollama/convert/reader_torch.go +++ /dev/null @@ -1,47 +0,0 @@ -package convert - -import ( - "io" - "io/fs" - - "github.com/nlpodyssey/gopickle/pytorch" - "github.com/nlpodyssey/gopickle/types" -) - -func parseTorch(fsys fs.FS, ps ...string) ([]Tensor, error) { - var ts []Tensor - for _, p := range ps { - pt, err := pytorch.Load(p) - if err != nil { - return nil, err - } - - for _, k := range pt.(*types.Dict).Keys() { - t := pt.(*types.Dict).MustGet(k) - - var shape []uint64 - for dim := range t.(*pytorch.Tensor).Size { - shape = append(shape, uint64(dim)) - } - - ts = append(ts, torch{ - storage: t.(*pytorch.Tensor).Source, - tensorBase: &tensorBase{ - name: k.(string), - shape: shape, - }, - }) - } - } - - return ts, nil -} - -type torch struct { - storage pytorch.StorageInterface - *tensorBase -} - -func (pt torch) WriteTo(w io.Writer) (int64, error) { - return 0, nil -} diff --git a/ollama/convert/sentencepiece/sentencepiece_model.pb.go b/ollama/convert/sentencepiece/sentencepiece_model.pb.go deleted file mode 100755 index 5c8db9b..0000000 --- a/ollama/convert/sentencepiece/sentencepiece_model.pb.go +++ /dev/null @@ -1,1497 +0,0 @@ -// Copyright 2016 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.! - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 -// source: sentencepiece_model.proto - -package sentencepiece - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Model type. only have UNIGRAM now. -type TrainerSpec_ModelType int32 - -const ( - TrainerSpec_UNIGRAM TrainerSpec_ModelType = 1 // Unigram language model with dynamic algorithm - TrainerSpec_BPE TrainerSpec_ModelType = 2 // Byte Pair Encoding - TrainerSpec_WORD TrainerSpec_ModelType = 3 // Delimitered by whitespace. - TrainerSpec_CHAR TrainerSpec_ModelType = 4 // tokenizes into character sequence -) - -// Enum value maps for TrainerSpec_ModelType. -var ( - TrainerSpec_ModelType_name = map[int32]string{ - 1: "UNIGRAM", - 2: "BPE", - 3: "WORD", - 4: "CHAR", - } - TrainerSpec_ModelType_value = map[string]int32{ - "UNIGRAM": 1, - "BPE": 2, - "WORD": 3, - "CHAR": 4, - } -) - -func (x TrainerSpec_ModelType) Enum() *TrainerSpec_ModelType { - p := new(TrainerSpec_ModelType) - *p = x - return p -} - -func (x TrainerSpec_ModelType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TrainerSpec_ModelType) Descriptor() protoreflect.EnumDescriptor { - return file_sentencepiece_model_proto_enumTypes[0].Descriptor() -} - -func (TrainerSpec_ModelType) Type() protoreflect.EnumType { - return &file_sentencepiece_model_proto_enumTypes[0] -} - -func (x TrainerSpec_ModelType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *TrainerSpec_ModelType) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = TrainerSpec_ModelType(num) - return nil -} - -// Deprecated: Use TrainerSpec_ModelType.Descriptor instead. -func (TrainerSpec_ModelType) EnumDescriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{0, 0} -} - -type ModelProto_SentencePiece_Type int32 - -const ( - ModelProto_SentencePiece_NORMAL ModelProto_SentencePiece_Type = 1 // normal symbol - ModelProto_SentencePiece_UNKNOWN ModelProto_SentencePiece_Type = 2 // unknown symbol. only for now. - ModelProto_SentencePiece_CONTROL ModelProto_SentencePiece_Type = 3 // control symbols. , , <2ja> etc. - ModelProto_SentencePiece_USER_DEFINED ModelProto_SentencePiece_Type = 4 // user defined symbols. - // Typical usage of USER_DEFINED symbol - // is placeholder. - ModelProto_SentencePiece_BYTE ModelProto_SentencePiece_Type = 6 // byte symbols. Used when `byte_fallback` is true. - ModelProto_SentencePiece_UNUSED ModelProto_SentencePiece_Type = 5 // this piece is not used. -) - -// Enum value maps for ModelProto_SentencePiece_Type. -var ( - ModelProto_SentencePiece_Type_name = map[int32]string{ - 1: "NORMAL", - 2: "UNKNOWN", - 3: "CONTROL", - 4: "USER_DEFINED", - 6: "BYTE", - 5: "UNUSED", - } - ModelProto_SentencePiece_Type_value = map[string]int32{ - "NORMAL": 1, - "UNKNOWN": 2, - "CONTROL": 3, - "USER_DEFINED": 4, - "BYTE": 6, - "UNUSED": 5, - } -) - -func (x ModelProto_SentencePiece_Type) Enum() *ModelProto_SentencePiece_Type { - p := new(ModelProto_SentencePiece_Type) - *p = x - return p -} - -func (x ModelProto_SentencePiece_Type) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ModelProto_SentencePiece_Type) Descriptor() protoreflect.EnumDescriptor { - return file_sentencepiece_model_proto_enumTypes[1].Descriptor() -} - -func (ModelProto_SentencePiece_Type) Type() protoreflect.EnumType { - return &file_sentencepiece_model_proto_enumTypes[1] -} - -func (x ModelProto_SentencePiece_Type) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *ModelProto_SentencePiece_Type) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = ModelProto_SentencePiece_Type(num) - return nil -} - -// Deprecated: Use ModelProto_SentencePiece_Type.Descriptor instead. -func (ModelProto_SentencePiece_Type) EnumDescriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{3, 0, 0} -} - -// TrainerSpec encodes a various parameters for SentencePiece training. -// Next id: 55 -type TrainerSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - extensionFields protoimpl.ExtensionFields - - // ///////////////////////////////////////////////////////////////// - // General parameters - // - // Input corpus files. - // - // Trainer accepts the following two formats: - // A) Monolingual: plain text, one sentence per line. - // B) Bilingual: TSV, source sentence target sentence - // When bilingual data is passed, shared vocabulary model is built. - // Note that the input file must be raw corpus, not a preprocessed corpus. - // Trainer only loads the first `input_sentence_size` sentences specified - // with this parameter. - Input []string `protobuf:"bytes,1,rep,name=input" json:"input,omitempty"` - // Input corpus format: - // "text": one-sentence-per-line text format (default) - // "tsv": sentence freq - InputFormat *string `protobuf:"bytes,7,opt,name=input_format,json=inputFormat" json:"input_format,omitempty"` - // Output model file prefix. - // .model and .vocab are generated. - ModelPrefix *string `protobuf:"bytes,2,opt,name=model_prefix,json=modelPrefix" json:"model_prefix,omitempty"` - ModelType *TrainerSpec_ModelType `protobuf:"varint,3,opt,name=model_type,json=modelType,enum=sentencepiece.TrainerSpec_ModelType,def=1" json:"model_type,omitempty"` - // Vocabulary size. 8k is the default size. - VocabSize *int32 `protobuf:"varint,4,opt,name=vocab_size,json=vocabSize,def=8000" json:"vocab_size,omitempty"` - // List of the languages this model can accept. - // Since the model is language-agnostic, this field is used as a reference. - AcceptLanguage []string `protobuf:"bytes,5,rep,name=accept_language,json=acceptLanguage" json:"accept_language,omitempty"` - // Size of self-test samples, which are encoded in the model file. - SelfTestSampleSize *int32 `protobuf:"varint,6,opt,name=self_test_sample_size,json=selfTestSampleSize,def=0" json:"self_test_sample_size,omitempty"` - // Whether to use DP version of sentencepiece. Use it with TSV input format - // (requires precomputed word tab counts to work). - EnableDifferentialPrivacy *bool `protobuf:"varint,50,opt,name=enable_differential_privacy,json=enableDifferentialPrivacy,def=0" json:"enable_differential_privacy,omitempty"` - // Set these parameters if you need DP version of sentencepiece. - // std of noise to add. - DifferentialPrivacyNoiseLevel *float32 `protobuf:"fixed32,51,opt,name=differential_privacy_noise_level,json=differentialPrivacyNoiseLevel,def=0" json:"differential_privacy_noise_level,omitempty"` - // Clipping threshold to apply after adding noise. All the words with - // frequency less than this value are dropped. - DifferentialPrivacyClippingThreshold *uint64 `protobuf:"varint,52,opt,name=differential_privacy_clipping_threshold,json=differentialPrivacyClippingThreshold,def=0" json:"differential_privacy_clipping_threshold,omitempty"` - // ///////////////////////////////////////////////////////////////// - // Training parameters. - // - // Uses characters which cover the corpus with the ratio of `chars_coverage`. - // This parameter determines the set of basic Alphabet of sentence piece. - // 1.0 - `chars_coverage` characters are treated as UNK. - // See also required_chars field. - CharacterCoverage *float32 `protobuf:"fixed32,10,opt,name=character_coverage,json=characterCoverage,def=0.9995" json:"character_coverage,omitempty"` - // Maximum size of sentences the trainer loads from `input` parameter. - // Trainer simply loads the `input` files in sequence. - // It is better to shuffle the input corpus randomly. - InputSentenceSize *uint64 `protobuf:"varint,11,opt,name=input_sentence_size,json=inputSentenceSize,def=0" json:"input_sentence_size,omitempty"` - ShuffleInputSentence *bool `protobuf:"varint,19,opt,name=shuffle_input_sentence,json=shuffleInputSentence,def=1" json:"shuffle_input_sentence,omitempty"` - // Maximum size of sentences to make seed sentence pieces. - // Extended suffix array is constructed to extract frequent - // sub-strings from the corpus. This uses 20N working space, - // where N is the size of corpus. - // - // Deprecated: Marked as deprecated in sentencepiece_model.proto. - MiningSentenceSize *int32 `protobuf:"varint,12,opt,name=mining_sentence_size,json=miningSentenceSize" json:"mining_sentence_size,omitempty"` - // Maximum size of sentences to train sentence pieces. - // - // Deprecated: Marked as deprecated in sentencepiece_model.proto. - TrainingSentenceSize *int32 `protobuf:"varint,13,opt,name=training_sentence_size,json=trainingSentenceSize" json:"training_sentence_size,omitempty"` - // The size of seed sentencepieces. - // `seed_sentencepiece_size` must be larger than `vocab_size`. - SeedSentencepieceSize *int32 `protobuf:"varint,14,opt,name=seed_sentencepiece_size,json=seedSentencepieceSize,def=1000000" json:"seed_sentencepiece_size,omitempty"` - // In every EM sub-iterations, keeps top - // `shrinking_factor` * `current sentencepieces size` with respect to - // the loss of the sentence piece. This value should be smaller than 1.0. - ShrinkingFactor *float32 `protobuf:"fixed32,15,opt,name=shrinking_factor,json=shrinkingFactor,def=0.75" json:"shrinking_factor,omitempty"` - // The maximum sentence length in byte. The sentences with the length - // larger than `max_sentence_length` is simply ignored. - // Longer input tends to bring the following risks: - // - Overflow during EM training (unigram language model only) - // - Performance drop because of O(n log n) cost in BPE. - MaxSentenceLength *int32 `protobuf:"varint,18,opt,name=max_sentence_length,json=maxSentenceLength,def=4192" json:"max_sentence_length,omitempty"` - // Number of threads in the training. - NumThreads *int32 `protobuf:"varint,16,opt,name=num_threads,json=numThreads,def=16" json:"num_threads,omitempty"` - // Number of EM sub iterations. - NumSubIterations *int32 `protobuf:"varint,17,opt,name=num_sub_iterations,json=numSubIterations,def=2" json:"num_sub_iterations,omitempty"` - // ///////////////////////////////////////////////////////////////// - // SentencePiece parameters which control the shapes of sentence piece. - // - // Maximum length of sentencepiece. - MaxSentencepieceLength *int32 `protobuf:"varint,20,opt,name=max_sentencepiece_length,json=maxSentencepieceLength,def=16" json:"max_sentencepiece_length,omitempty"` - // Uses Unicode script to split sentence pieces. - // When `split_by_unicode_script` is true, we do not allow sentence piece to - // include multiple Unicode scripts, e.g. "F1" is not a valid piece. - // Exception: CJ characters (Hiragana/Katakana/Han) are all handled - // as one script type, since Japanese word can consist of multiple scripts. - // This exception is always applied regardless of the accept-language - // parameter. - SplitByUnicodeScript *bool `protobuf:"varint,21,opt,name=split_by_unicode_script,json=splitByUnicodeScript,def=1" json:"split_by_unicode_script,omitempty"` - // When `split_by_number` is true, put a boundary between number and - // non-number transition. If we want to treat "F1" is one token, set this flag - // to be false. - SplitByNumber *bool `protobuf:"varint,23,opt,name=split_by_number,json=splitByNumber,def=1" json:"split_by_number,omitempty"` - // Use a white space to split sentence pieces. - // When `split_by_whitespace` is false, we may have the piece containing - // a white space in the middle. e.g., "in_the". - SplitByWhitespace *bool `protobuf:"varint,22,opt,name=split_by_whitespace,json=splitByWhitespace,def=1" json:"split_by_whitespace,omitempty"` - // Adds whitespace symbol (_) as a suffix instead of prefix. e.g., _hello => - // hello_. When `treat_whitespace_as_suffix` is true, - // NormalizerSpec::add_dummy_prefix will add the dummy whitespace to the end - // of sentence. - TreatWhitespaceAsSuffix *bool `protobuf:"varint,24,opt,name=treat_whitespace_as_suffix,json=treatWhitespaceAsSuffix,def=0" json:"treat_whitespace_as_suffix,omitempty"` - // Allows pieces that only contain whitespaces instead of appearing only as - // prefix or suffix of other pieces. - AllowWhitespaceOnlyPieces *bool `protobuf:"varint,26,opt,name=allow_whitespace_only_pieces,json=allowWhitespaceOnlyPieces,def=0" json:"allow_whitespace_only_pieces,omitempty"` - // Split all digits (0-9) into separate pieces. - SplitDigits *bool `protobuf:"varint,25,opt,name=split_digits,json=splitDigits,def=0" json:"split_digits,omitempty"` - // Defines the pre-tokenization delimiter. - // When specified, no pieces crossing this delimiter is not included - // in the vocab. Then the delimiter string is virtually ignored - // during the training. This field can allows constraints on the vocabulary - // selection. Note that this field is available on unigram mode. - PretokenizationDelimiter *string `protobuf:"bytes,53,opt,name=pretokenization_delimiter,json=pretokenizationDelimiter,def=" json:"pretokenization_delimiter,omitempty"` - // ///////////////////////////////////////////////////////////////// - // Vocabulary management - // - // Defines control symbols used as an indicator to - // change the behavior of the decoder. and are pre-defined. - // We can use this field to encode various meta information, - // including language indicator in multilingual model. - // These symbols are not visible to users, but visible to - // the decoder. Note that when the input sentence contains control symbols, - // they are not treated as one token, but segmented into normal pieces. - // Control symbols must be inserted independently from the segmentation. - ControlSymbols []string `protobuf:"bytes,30,rep,name=control_symbols,json=controlSymbols" json:"control_symbols,omitempty"` - // Defines user defined symbols. - // These symbols are added with extremely high score - // so they are always treated as one unique symbol in any context. - // Typical usage of user_defined_symbols is placeholder for named entities. - UserDefinedSymbols []string `protobuf:"bytes,31,rep,name=user_defined_symbols,json=userDefinedSymbols" json:"user_defined_symbols,omitempty"` - // Defines required characters. Each UTF8 character in this string is included - // in the character set regardless of character_coverage value. Unlike - // user_defined_symbols, these characters have scores based on the frequency - // on input sentences, and the model can form subwords using characters - // in this field. - RequiredChars *string `protobuf:"bytes,36,opt,name=required_chars,json=requiredChars" json:"required_chars,omitempty"` - // Decomposes unknown pieces into UTF-8 bytes. - ByteFallback *bool `protobuf:"varint,35,opt,name=byte_fallback,json=byteFallback,def=0" json:"byte_fallback,omitempty"` - // When creating the vocabulary file, defines whether or not to additionally - // output the score for each piece. - VocabularyOutputPieceScore *bool `protobuf:"varint,32,opt,name=vocabulary_output_piece_score,json=vocabularyOutputPieceScore,def=1" json:"vocabulary_output_piece_score,omitempty"` - // `vocab_size` is treated as hard limit. Crash if - // the model can not produce the vocab of size `vocab_size`, - // When `hard_vocab_limit` is false, vocab_size is treated - // as soft limit. Note that when model_type=char, - // always assumes hard_vocab_limit = false. - HardVocabLimit *bool `protobuf:"varint,33,opt,name=hard_vocab_limit,json=hardVocabLimit,def=1" json:"hard_vocab_limit,omitempty"` - // use all symbols for vocab extraction. This flag is valid - // if model type is either CHAR or WORD - UseAllVocab *bool `protobuf:"varint,34,opt,name=use_all_vocab,json=useAllVocab,def=0" json:"use_all_vocab,omitempty"` - // ///////////////////////////////////////////////////////////////// - // Reserved special meta tokens. - // * -1 is not used. - // * unk_id must not be -1. - // Id must starts with 0 and be contigous. - UnkId *int32 `protobuf:"varint,40,opt,name=unk_id,json=unkId,def=0" json:"unk_id,omitempty"` // - BosId *int32 `protobuf:"varint,41,opt,name=bos_id,json=bosId,def=1" json:"bos_id,omitempty"` // - EosId *int32 `protobuf:"varint,42,opt,name=eos_id,json=eosId,def=2" json:"eos_id,omitempty"` // - PadId *int32 `protobuf:"varint,43,opt,name=pad_id,json=padId,def=-1" json:"pad_id,omitempty"` // (padding) - UnkPiece *string `protobuf:"bytes,45,opt,name=unk_piece,json=unkPiece,def=" json:"unk_piece,omitempty"` - BosPiece *string `protobuf:"bytes,46,opt,name=bos_piece,json=bosPiece,def=" json:"bos_piece,omitempty"` - EosPiece *string `protobuf:"bytes,47,opt,name=eos_piece,json=eosPiece,def=" json:"eos_piece,omitempty"` - PadPiece *string `protobuf:"bytes,48,opt,name=pad_piece,json=padPiece,def=" json:"pad_piece,omitempty"` - // Encodes into U+2047 (DOUBLE QUESTION MARK), - // since this character can be useful both for user and - // developer. We can easily figure out that is emitted. - UnkSurface *string `protobuf:"bytes,44,opt,name=unk_surface,json=unkSurface,def= ⁇ " json:"unk_surface,omitempty"` - // Increase bit depth to allow unigram model training on large - // (>10M sentences) corpora. A Side-effect of enabling this flag - // is increased memory usage. - TrainExtremelyLargeCorpus *bool `protobuf:"varint,49,opt,name=train_extremely_large_corpus,json=trainExtremelyLargeCorpus,def=0" json:"train_extremely_large_corpus,omitempty"` - // Path to a seed sentencepieces file, with one tab-separated - // seed sentencepiece frequency per line. - SeedSentencepiecesFile *string `protobuf:"bytes,54,opt,name=seed_sentencepieces_file,json=seedSentencepiecesFile,def=" json:"seed_sentencepieces_file,omitempty"` -} - -// Default values for TrainerSpec fields. -const ( - Default_TrainerSpec_ModelType = TrainerSpec_UNIGRAM - Default_TrainerSpec_VocabSize = int32(8000) - Default_TrainerSpec_SelfTestSampleSize = int32(0) - Default_TrainerSpec_EnableDifferentialPrivacy = bool(false) - Default_TrainerSpec_DifferentialPrivacyNoiseLevel = float32(0) - Default_TrainerSpec_DifferentialPrivacyClippingThreshold = uint64(0) - Default_TrainerSpec_CharacterCoverage = float32(0.9994999766349792) - Default_TrainerSpec_InputSentenceSize = uint64(0) - Default_TrainerSpec_ShuffleInputSentence = bool(true) - Default_TrainerSpec_SeedSentencepieceSize = int32(1000000) - Default_TrainerSpec_ShrinkingFactor = float32(0.75) - Default_TrainerSpec_MaxSentenceLength = int32(4192) - Default_TrainerSpec_NumThreads = int32(16) - Default_TrainerSpec_NumSubIterations = int32(2) - Default_TrainerSpec_MaxSentencepieceLength = int32(16) - Default_TrainerSpec_SplitByUnicodeScript = bool(true) - Default_TrainerSpec_SplitByNumber = bool(true) - Default_TrainerSpec_SplitByWhitespace = bool(true) - Default_TrainerSpec_TreatWhitespaceAsSuffix = bool(false) - Default_TrainerSpec_AllowWhitespaceOnlyPieces = bool(false) - Default_TrainerSpec_SplitDigits = bool(false) - Default_TrainerSpec_PretokenizationDelimiter = string("") - Default_TrainerSpec_ByteFallback = bool(false) - Default_TrainerSpec_VocabularyOutputPieceScore = bool(true) - Default_TrainerSpec_HardVocabLimit = bool(true) - Default_TrainerSpec_UseAllVocab = bool(false) - Default_TrainerSpec_UnkId = int32(0) - Default_TrainerSpec_BosId = int32(1) - Default_TrainerSpec_EosId = int32(2) - Default_TrainerSpec_PadId = int32(-1) - Default_TrainerSpec_UnkPiece = string("") - Default_TrainerSpec_BosPiece = string("") - Default_TrainerSpec_EosPiece = string("") - Default_TrainerSpec_PadPiece = string("") - Default_TrainerSpec_UnkSurface = string(" ⁇ ") - Default_TrainerSpec_TrainExtremelyLargeCorpus = bool(false) - Default_TrainerSpec_SeedSentencepiecesFile = string("") -) - -func (x *TrainerSpec) Reset() { - *x = TrainerSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrainerSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrainerSpec) ProtoMessage() {} - -func (x *TrainerSpec) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrainerSpec.ProtoReflect.Descriptor instead. -func (*TrainerSpec) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{0} -} - -func (x *TrainerSpec) GetInput() []string { - if x != nil { - return x.Input - } - return nil -} - -func (x *TrainerSpec) GetInputFormat() string { - if x != nil && x.InputFormat != nil { - return *x.InputFormat - } - return "" -} - -func (x *TrainerSpec) GetModelPrefix() string { - if x != nil && x.ModelPrefix != nil { - return *x.ModelPrefix - } - return "" -} - -func (x *TrainerSpec) GetModelType() TrainerSpec_ModelType { - if x != nil && x.ModelType != nil { - return *x.ModelType - } - return Default_TrainerSpec_ModelType -} - -func (x *TrainerSpec) GetVocabSize() int32 { - if x != nil && x.VocabSize != nil { - return *x.VocabSize - } - return Default_TrainerSpec_VocabSize -} - -func (x *TrainerSpec) GetAcceptLanguage() []string { - if x != nil { - return x.AcceptLanguage - } - return nil -} - -func (x *TrainerSpec) GetSelfTestSampleSize() int32 { - if x != nil && x.SelfTestSampleSize != nil { - return *x.SelfTestSampleSize - } - return Default_TrainerSpec_SelfTestSampleSize -} - -func (x *TrainerSpec) GetEnableDifferentialPrivacy() bool { - if x != nil && x.EnableDifferentialPrivacy != nil { - return *x.EnableDifferentialPrivacy - } - return Default_TrainerSpec_EnableDifferentialPrivacy -} - -func (x *TrainerSpec) GetDifferentialPrivacyNoiseLevel() float32 { - if x != nil && x.DifferentialPrivacyNoiseLevel != nil { - return *x.DifferentialPrivacyNoiseLevel - } - return Default_TrainerSpec_DifferentialPrivacyNoiseLevel -} - -func (x *TrainerSpec) GetDifferentialPrivacyClippingThreshold() uint64 { - if x != nil && x.DifferentialPrivacyClippingThreshold != nil { - return *x.DifferentialPrivacyClippingThreshold - } - return Default_TrainerSpec_DifferentialPrivacyClippingThreshold -} - -func (x *TrainerSpec) GetCharacterCoverage() float32 { - if x != nil && x.CharacterCoverage != nil { - return *x.CharacterCoverage - } - return Default_TrainerSpec_CharacterCoverage -} - -func (x *TrainerSpec) GetInputSentenceSize() uint64 { - if x != nil && x.InputSentenceSize != nil { - return *x.InputSentenceSize - } - return Default_TrainerSpec_InputSentenceSize -} - -func (x *TrainerSpec) GetShuffleInputSentence() bool { - if x != nil && x.ShuffleInputSentence != nil { - return *x.ShuffleInputSentence - } - return Default_TrainerSpec_ShuffleInputSentence -} - -// Deprecated: Marked as deprecated in sentencepiece_model.proto. -func (x *TrainerSpec) GetMiningSentenceSize() int32 { - if x != nil && x.MiningSentenceSize != nil { - return *x.MiningSentenceSize - } - return 0 -} - -// Deprecated: Marked as deprecated in sentencepiece_model.proto. -func (x *TrainerSpec) GetTrainingSentenceSize() int32 { - if x != nil && x.TrainingSentenceSize != nil { - return *x.TrainingSentenceSize - } - return 0 -} - -func (x *TrainerSpec) GetSeedSentencepieceSize() int32 { - if x != nil && x.SeedSentencepieceSize != nil { - return *x.SeedSentencepieceSize - } - return Default_TrainerSpec_SeedSentencepieceSize -} - -func (x *TrainerSpec) GetShrinkingFactor() float32 { - if x != nil && x.ShrinkingFactor != nil { - return *x.ShrinkingFactor - } - return Default_TrainerSpec_ShrinkingFactor -} - -func (x *TrainerSpec) GetMaxSentenceLength() int32 { - if x != nil && x.MaxSentenceLength != nil { - return *x.MaxSentenceLength - } - return Default_TrainerSpec_MaxSentenceLength -} - -func (x *TrainerSpec) GetNumThreads() int32 { - if x != nil && x.NumThreads != nil { - return *x.NumThreads - } - return Default_TrainerSpec_NumThreads -} - -func (x *TrainerSpec) GetNumSubIterations() int32 { - if x != nil && x.NumSubIterations != nil { - return *x.NumSubIterations - } - return Default_TrainerSpec_NumSubIterations -} - -func (x *TrainerSpec) GetMaxSentencepieceLength() int32 { - if x != nil && x.MaxSentencepieceLength != nil { - return *x.MaxSentencepieceLength - } - return Default_TrainerSpec_MaxSentencepieceLength -} - -func (x *TrainerSpec) GetSplitByUnicodeScript() bool { - if x != nil && x.SplitByUnicodeScript != nil { - return *x.SplitByUnicodeScript - } - return Default_TrainerSpec_SplitByUnicodeScript -} - -func (x *TrainerSpec) GetSplitByNumber() bool { - if x != nil && x.SplitByNumber != nil { - return *x.SplitByNumber - } - return Default_TrainerSpec_SplitByNumber -} - -func (x *TrainerSpec) GetSplitByWhitespace() bool { - if x != nil && x.SplitByWhitespace != nil { - return *x.SplitByWhitespace - } - return Default_TrainerSpec_SplitByWhitespace -} - -func (x *TrainerSpec) GetTreatWhitespaceAsSuffix() bool { - if x != nil && x.TreatWhitespaceAsSuffix != nil { - return *x.TreatWhitespaceAsSuffix - } - return Default_TrainerSpec_TreatWhitespaceAsSuffix -} - -func (x *TrainerSpec) GetAllowWhitespaceOnlyPieces() bool { - if x != nil && x.AllowWhitespaceOnlyPieces != nil { - return *x.AllowWhitespaceOnlyPieces - } - return Default_TrainerSpec_AllowWhitespaceOnlyPieces -} - -func (x *TrainerSpec) GetSplitDigits() bool { - if x != nil && x.SplitDigits != nil { - return *x.SplitDigits - } - return Default_TrainerSpec_SplitDigits -} - -func (x *TrainerSpec) GetPretokenizationDelimiter() string { - if x != nil && x.PretokenizationDelimiter != nil { - return *x.PretokenizationDelimiter - } - return Default_TrainerSpec_PretokenizationDelimiter -} - -func (x *TrainerSpec) GetControlSymbols() []string { - if x != nil { - return x.ControlSymbols - } - return nil -} - -func (x *TrainerSpec) GetUserDefinedSymbols() []string { - if x != nil { - return x.UserDefinedSymbols - } - return nil -} - -func (x *TrainerSpec) GetRequiredChars() string { - if x != nil && x.RequiredChars != nil { - return *x.RequiredChars - } - return "" -} - -func (x *TrainerSpec) GetByteFallback() bool { - if x != nil && x.ByteFallback != nil { - return *x.ByteFallback - } - return Default_TrainerSpec_ByteFallback -} - -func (x *TrainerSpec) GetVocabularyOutputPieceScore() bool { - if x != nil && x.VocabularyOutputPieceScore != nil { - return *x.VocabularyOutputPieceScore - } - return Default_TrainerSpec_VocabularyOutputPieceScore -} - -func (x *TrainerSpec) GetHardVocabLimit() bool { - if x != nil && x.HardVocabLimit != nil { - return *x.HardVocabLimit - } - return Default_TrainerSpec_HardVocabLimit -} - -func (x *TrainerSpec) GetUseAllVocab() bool { - if x != nil && x.UseAllVocab != nil { - return *x.UseAllVocab - } - return Default_TrainerSpec_UseAllVocab -} - -func (x *TrainerSpec) GetUnkId() int32 { - if x != nil && x.UnkId != nil { - return *x.UnkId - } - return Default_TrainerSpec_UnkId -} - -func (x *TrainerSpec) GetBosId() int32 { - if x != nil && x.BosId != nil { - return *x.BosId - } - return Default_TrainerSpec_BosId -} - -func (x *TrainerSpec) GetEosId() int32 { - if x != nil && x.EosId != nil { - return *x.EosId - } - return Default_TrainerSpec_EosId -} - -func (x *TrainerSpec) GetPadId() int32 { - if x != nil && x.PadId != nil { - return *x.PadId - } - return Default_TrainerSpec_PadId -} - -func (x *TrainerSpec) GetUnkPiece() string { - if x != nil && x.UnkPiece != nil { - return *x.UnkPiece - } - return Default_TrainerSpec_UnkPiece -} - -func (x *TrainerSpec) GetBosPiece() string { - if x != nil && x.BosPiece != nil { - return *x.BosPiece - } - return Default_TrainerSpec_BosPiece -} - -func (x *TrainerSpec) GetEosPiece() string { - if x != nil && x.EosPiece != nil { - return *x.EosPiece - } - return Default_TrainerSpec_EosPiece -} - -func (x *TrainerSpec) GetPadPiece() string { - if x != nil && x.PadPiece != nil { - return *x.PadPiece - } - return Default_TrainerSpec_PadPiece -} - -func (x *TrainerSpec) GetUnkSurface() string { - if x != nil && x.UnkSurface != nil { - return *x.UnkSurface - } - return Default_TrainerSpec_UnkSurface -} - -func (x *TrainerSpec) GetTrainExtremelyLargeCorpus() bool { - if x != nil && x.TrainExtremelyLargeCorpus != nil { - return *x.TrainExtremelyLargeCorpus - } - return Default_TrainerSpec_TrainExtremelyLargeCorpus -} - -func (x *TrainerSpec) GetSeedSentencepiecesFile() string { - if x != nil && x.SeedSentencepiecesFile != nil { - return *x.SeedSentencepiecesFile - } - return Default_TrainerSpec_SeedSentencepiecesFile -} - -// NormalizerSpec encodes a various parameters for string normalizaiton -type NormalizerSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - extensionFields protoimpl.ExtensionFields - - // name of normalization rule. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // Pre-compiled normalization rule created by - // Builder::GetPrecompiledCharsMap() or Builder::CompileCharsMap() method. - // Usually this field is set by Builder::GetNormalizerSpec() method. - PrecompiledCharsmap []byte `protobuf:"bytes,2,opt,name=precompiled_charsmap,json=precompiledCharsmap" json:"precompiled_charsmap,omitempty"` - // Adds dummy whitespace at the beginning of text in order to - // treat "world" in "world" and "hello world" in the same way. - AddDummyPrefix *bool `protobuf:"varint,3,opt,name=add_dummy_prefix,json=addDummyPrefix,def=1" json:"add_dummy_prefix,omitempty"` - // Removes leading, trailing, and duplicate internal whitespace. - RemoveExtraWhitespaces *bool `protobuf:"varint,4,opt,name=remove_extra_whitespaces,json=removeExtraWhitespaces,def=1" json:"remove_extra_whitespaces,omitempty"` - // Replaces whitespace with meta symbol. - // This field must be true to train sentence piece model. - EscapeWhitespaces *bool `protobuf:"varint,5,opt,name=escape_whitespaces,json=escapeWhitespaces,def=1" json:"escape_whitespaces,omitempty"` - // Custom normalization rule file in TSV format. - // https://github.com/google/sentencepiece/blob/master/doc/normalization.md - // This field is only used in SentencePieceTrainer::Train() method, which - // compiles the rule into the binary rule stored in `precompiled_charsmap`. - NormalizationRuleTsv *string `protobuf:"bytes,6,opt,name=normalization_rule_tsv,json=normalizationRuleTsv" json:"normalization_rule_tsv,omitempty"` -} - -// Default values for NormalizerSpec fields. -const ( - Default_NormalizerSpec_AddDummyPrefix = bool(true) - Default_NormalizerSpec_RemoveExtraWhitespaces = bool(true) - Default_NormalizerSpec_EscapeWhitespaces = bool(true) -) - -func (x *NormalizerSpec) Reset() { - *x = NormalizerSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NormalizerSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NormalizerSpec) ProtoMessage() {} - -func (x *NormalizerSpec) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NormalizerSpec.ProtoReflect.Descriptor instead. -func (*NormalizerSpec) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{1} -} - -func (x *NormalizerSpec) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *NormalizerSpec) GetPrecompiledCharsmap() []byte { - if x != nil { - return x.PrecompiledCharsmap - } - return nil -} - -func (x *NormalizerSpec) GetAddDummyPrefix() bool { - if x != nil && x.AddDummyPrefix != nil { - return *x.AddDummyPrefix - } - return Default_NormalizerSpec_AddDummyPrefix -} - -func (x *NormalizerSpec) GetRemoveExtraWhitespaces() bool { - if x != nil && x.RemoveExtraWhitespaces != nil { - return *x.RemoveExtraWhitespaces - } - return Default_NormalizerSpec_RemoveExtraWhitespaces -} - -func (x *NormalizerSpec) GetEscapeWhitespaces() bool { - if x != nil && x.EscapeWhitespaces != nil { - return *x.EscapeWhitespaces - } - return Default_NormalizerSpec_EscapeWhitespaces -} - -func (x *NormalizerSpec) GetNormalizationRuleTsv() string { - if x != nil && x.NormalizationRuleTsv != nil { - return *x.NormalizationRuleTsv - } - return "" -} - -// Proto to store samples for self-testing. -type SelfTestData struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - extensionFields protoimpl.ExtensionFields - - Samples []*SelfTestData_Sample `protobuf:"bytes,1,rep,name=samples" json:"samples,omitempty"` -} - -func (x *SelfTestData) Reset() { - *x = SelfTestData{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SelfTestData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelfTestData) ProtoMessage() {} - -func (x *SelfTestData) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelfTestData.ProtoReflect.Descriptor instead. -func (*SelfTestData) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{2} -} - -func (x *SelfTestData) GetSamples() []*SelfTestData_Sample { - if x != nil { - return x.Samples - } - return nil -} - -// ModelProto stores model parameters. -// SentencePieceProcessor is supposed to be self-contained. -// All settings/parameters which may change the behavior must be encoded -// in ModelProto. -type ModelProto struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - extensionFields protoimpl.ExtensionFields - - // Sentence pieces with scores. - Pieces []*ModelProto_SentencePiece `protobuf:"bytes,1,rep,name=pieces" json:"pieces,omitempty"` - // Spec used to generate this model file. - TrainerSpec *TrainerSpec `protobuf:"bytes,2,opt,name=trainer_spec,json=trainerSpec" json:"trainer_spec,omitempty"` - // Spec for text normalization. - NormalizerSpec *NormalizerSpec `protobuf:"bytes,3,opt,name=normalizer_spec,json=normalizerSpec" json:"normalizer_spec,omitempty"` - // Stores sample input and its expected segmentation to verify the model. - SelfTestData *SelfTestData `protobuf:"bytes,4,opt,name=self_test_data,json=selfTestData" json:"self_test_data,omitempty"` - // Spec for text de-normalization. - DenormalizerSpec *NormalizerSpec `protobuf:"bytes,5,opt,name=denormalizer_spec,json=denormalizerSpec" json:"denormalizer_spec,omitempty"` -} - -func (x *ModelProto) Reset() { - *x = ModelProto{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ModelProto) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ModelProto) ProtoMessage() {} - -func (x *ModelProto) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ModelProto.ProtoReflect.Descriptor instead. -func (*ModelProto) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{3} -} - -func (x *ModelProto) GetPieces() []*ModelProto_SentencePiece { - if x != nil { - return x.Pieces - } - return nil -} - -func (x *ModelProto) GetTrainerSpec() *TrainerSpec { - if x != nil { - return x.TrainerSpec - } - return nil -} - -func (x *ModelProto) GetNormalizerSpec() *NormalizerSpec { - if x != nil { - return x.NormalizerSpec - } - return nil -} - -func (x *ModelProto) GetSelfTestData() *SelfTestData { - if x != nil { - return x.SelfTestData - } - return nil -} - -func (x *ModelProto) GetDenormalizerSpec() *NormalizerSpec { - if x != nil { - return x.DenormalizerSpec - } - return nil -} - -type SelfTestData_Sample struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Input *string `protobuf:"bytes,1,opt,name=input" json:"input,omitempty"` - Expected *string `protobuf:"bytes,2,opt,name=expected" json:"expected,omitempty"` -} - -func (x *SelfTestData_Sample) Reset() { - *x = SelfTestData_Sample{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SelfTestData_Sample) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelfTestData_Sample) ProtoMessage() {} - -func (x *SelfTestData_Sample) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelfTestData_Sample.ProtoReflect.Descriptor instead. -func (*SelfTestData_Sample) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *SelfTestData_Sample) GetInput() string { - if x != nil && x.Input != nil { - return *x.Input - } - return "" -} - -func (x *SelfTestData_Sample) GetExpected() string { - if x != nil && x.Expected != nil { - return *x.Expected - } - return "" -} - -type ModelProto_SentencePiece struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - extensionFields protoimpl.ExtensionFields - - Piece *string `protobuf:"bytes,1,opt,name=piece" json:"piece,omitempty"` // piece must not be empty. - Score *float32 `protobuf:"fixed32,2,opt,name=score" json:"score,omitempty"` - Type *ModelProto_SentencePiece_Type `protobuf:"varint,3,opt,name=type,enum=sentencepiece.ModelProto_SentencePiece_Type,def=1" json:"type,omitempty"` -} - -// Default values for ModelProto_SentencePiece fields. -const ( - Default_ModelProto_SentencePiece_Type = ModelProto_SentencePiece_NORMAL -) - -func (x *ModelProto_SentencePiece) Reset() { - *x = ModelProto_SentencePiece{} - if protoimpl.UnsafeEnabled { - mi := &file_sentencepiece_model_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ModelProto_SentencePiece) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ModelProto_SentencePiece) ProtoMessage() {} - -func (x *ModelProto_SentencePiece) ProtoReflect() protoreflect.Message { - mi := &file_sentencepiece_model_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ModelProto_SentencePiece.ProtoReflect.Descriptor instead. -func (*ModelProto_SentencePiece) Descriptor() ([]byte, []int) { - return file_sentencepiece_model_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *ModelProto_SentencePiece) GetPiece() string { - if x != nil && x.Piece != nil { - return *x.Piece - } - return "" -} - -func (x *ModelProto_SentencePiece) GetScore() float32 { - if x != nil && x.Score != nil { - return *x.Score - } - return 0 -} - -func (x *ModelProto_SentencePiece) GetType() ModelProto_SentencePiece_Type { - if x != nil && x.Type != nil { - return *x.Type - } - return Default_ModelProto_SentencePiece_Type -} - -var File_sentencepiece_model_proto protoreflect.FileDescriptor - -var file_sentencepiece_model_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x5f, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x73, 0x65, 0x6e, - 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x22, 0xc6, 0x12, 0x0a, 0x0b, 0x54, - 0x72, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x4c, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x73, 0x65, 0x6e, - 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, - 0x3a, 0x07, 0x55, 0x4e, 0x49, 0x47, 0x52, 0x41, 0x4d, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0a, 0x76, 0x6f, 0x63, 0x61, 0x62, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x04, 0x38, 0x30, 0x30, 0x30, 0x52, 0x09, - 0x76, 0x6f, 0x63, 0x61, 0x62, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x12, 0x34, 0x0a, 0x15, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, - 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x05, 0x3a, 0x01, 0x30, 0x52, 0x12, 0x73, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x53, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x45, 0x0a, 0x1b, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x52, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x66, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x12, - 0x4a, 0x0a, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x5f, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x33, 0x20, 0x01, 0x28, 0x02, 0x3a, 0x01, 0x30, 0x52, 0x1d, 0x64, 0x69, - 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x72, 0x69, 0x76, 0x61, 0x63, - 0x79, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x27, 0x64, - 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x76, - 0x61, 0x63, 0x79, 0x5f, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x34, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, - 0x24, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x72, 0x69, - 0x76, 0x61, 0x63, 0x79, 0x43, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x35, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, - 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x02, 0x3a, 0x06, 0x30, 0x2e, 0x39, 0x39, 0x39, 0x35, 0x52, 0x11, 0x63, 0x68, 0x61, 0x72, 0x61, - 0x63, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, 0x13, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x11, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x3a, 0x0a, 0x16, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x3a, - 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x14, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x14, 0x6d, - 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x42, 0x02, 0x18, 0x01, 0x52, 0x12, 0x6d, - 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x38, 0x0a, 0x16, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, - 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x05, 0x42, 0x02, 0x18, 0x01, 0x52, 0x14, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x3f, 0x0a, 0x17, 0x73, - 0x65, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, - 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x07, 0x31, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x52, 0x15, 0x73, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x74, 0x65, - 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2f, 0x0a, 0x10, - 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x02, 0x3a, 0x04, 0x30, 0x2e, 0x37, 0x35, 0x52, 0x0f, 0x73, 0x68, - 0x72, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, - 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x04, 0x34, 0x31, 0x39, 0x32, - 0x52, 0x11, 0x6d, 0x61, 0x78, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, - 0x64, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x02, 0x31, 0x36, 0x52, 0x0a, 0x6e, 0x75, - 0x6d, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x6e, 0x75, 0x6d, 0x5f, - 0x73, 0x75, 0x62, 0x5f, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x11, - 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x32, 0x52, 0x10, 0x6e, 0x75, 0x6d, 0x53, 0x75, 0x62, 0x49, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x18, 0x6d, 0x61, 0x78, - 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x5f, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x02, 0x31, 0x36, 0x52, - 0x16, 0x6d, 0x61, 0x78, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x17, 0x73, 0x70, 0x6c, 0x69, 0x74, - 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x14, - 0x73, 0x70, 0x6c, 0x69, 0x74, 0x42, 0x79, 0x55, 0x6e, 0x69, 0x63, 0x6f, 0x64, 0x65, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x62, 0x79, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, - 0x72, 0x75, 0x65, 0x52, 0x0d, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x12, 0x34, 0x0a, 0x13, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x77, - 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x3a, - 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x11, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x42, 0x79, 0x57, 0x68, - 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x1a, 0x74, 0x72, 0x65, 0x61, - 0x74, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x73, 0x5f, - 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x52, 0x17, 0x74, 0x72, 0x65, 0x61, 0x74, 0x57, 0x68, 0x69, 0x74, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x41, 0x73, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x1c, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x18, 0x1a, 0x20, 0x01, - 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x57, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x69, - 0x65, 0x63, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0c, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x64, 0x69, - 0x67, 0x69, 0x74, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x52, 0x0b, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x44, 0x69, 0x67, 0x69, 0x74, 0x73, 0x12, 0x3d, - 0x0a, 0x19, 0x70, 0x72, 0x65, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x18, 0x35, 0x20, 0x01, 0x28, - 0x09, 0x3a, 0x00, 0x52, 0x18, 0x70, 0x72, 0x65, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x12, 0x27, 0x0a, - 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, - 0x18, 0x1e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, - 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x18, 0x1f, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, - 0x64, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x43, 0x68, 0x61, 0x72, 0x73, 0x12, - 0x2a, 0x0a, 0x0d, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, - 0x18, 0x23, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0c, 0x62, - 0x79, 0x74, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x1d, 0x76, - 0x6f, 0x63, 0x61, 0x62, 0x75, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x20, 0x20, 0x01, - 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x1a, 0x76, 0x6f, 0x63, 0x61, 0x62, 0x75, - 0x6c, 0x61, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x69, 0x65, 0x63, 0x65, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2e, 0x0a, 0x10, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x76, 0x6f, 0x63, - 0x61, 0x62, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, - 0x74, 0x72, 0x75, 0x65, 0x52, 0x0e, 0x68, 0x61, 0x72, 0x64, 0x56, 0x6f, 0x63, 0x61, 0x62, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x12, 0x29, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, - 0x76, 0x6f, 0x63, 0x61, 0x62, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, - 0x73, 0x65, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x6c, 0x56, 0x6f, 0x63, 0x61, 0x62, 0x12, - 0x18, 0x0a, 0x06, 0x75, 0x6e, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x28, 0x20, 0x01, 0x28, 0x05, 0x3a, - 0x01, 0x30, 0x52, 0x05, 0x75, 0x6e, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x06, 0x62, 0x6f, 0x73, - 0x5f, 0x69, 0x64, 0x18, 0x29, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x31, 0x52, 0x05, 0x62, 0x6f, - 0x73, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x06, 0x65, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x20, - 0x01, 0x28, 0x05, 0x3a, 0x01, 0x32, 0x52, 0x05, 0x65, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x19, 0x0a, - 0x06, 0x70, 0x61, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x02, 0x2d, - 0x31, 0x52, 0x05, 0x70, 0x61, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x09, 0x75, 0x6e, 0x6b, 0x5f, - 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x05, 0x3c, 0x75, 0x6e, - 0x6b, 0x3e, 0x52, 0x08, 0x75, 0x6e, 0x6b, 0x50, 0x69, 0x65, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x09, - 0x62, 0x6f, 0x73, 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x09, 0x3a, - 0x03, 0x3c, 0x73, 0x3e, 0x52, 0x08, 0x62, 0x6f, 0x73, 0x50, 0x69, 0x65, 0x63, 0x65, 0x12, 0x21, - 0x0a, 0x09, 0x65, 0x6f, 0x73, 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, - 0x09, 0x3a, 0x04, 0x3c, 0x2f, 0x73, 0x3e, 0x52, 0x08, 0x65, 0x6f, 0x73, 0x50, 0x69, 0x65, 0x63, - 0x65, 0x12, 0x22, 0x0a, 0x09, 0x70, 0x61, 0x64, 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x30, - 0x20, 0x01, 0x28, 0x09, 0x3a, 0x05, 0x3c, 0x70, 0x61, 0x64, 0x3e, 0x52, 0x08, 0x70, 0x61, 0x64, - 0x50, 0x69, 0x65, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0b, 0x75, 0x6e, 0x6b, 0x5f, 0x73, 0x75, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x05, 0x20, 0xe2, 0x81, 0x87, - 0x20, 0x52, 0x0a, 0x75, 0x6e, 0x6b, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x46, 0x0a, - 0x1c, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65, 0x6c, 0x79, - 0x5f, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x18, 0x31, 0x20, - 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x19, 0x74, 0x72, 0x61, 0x69, - 0x6e, 0x45, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65, 0x6c, 0x79, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x43, - 0x6f, 0x72, 0x70, 0x75, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x73, 0x65, 0x65, 0x64, 0x5f, 0x73, 0x65, - 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x5f, 0x66, 0x69, 0x6c, - 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x00, 0x52, 0x16, 0x73, 0x65, 0x65, 0x64, 0x53, - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x46, 0x69, 0x6c, - 0x65, 0x22, 0x35, 0x0a, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x4e, 0x49, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x42, - 0x50, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x4f, 0x52, 0x44, 0x10, 0x03, 0x12, 0x08, - 0x0a, 0x04, 0x43, 0x48, 0x41, 0x52, 0x10, 0x04, 0x2a, 0x09, 0x08, 0xc8, 0x01, 0x10, 0x80, 0x80, - 0x80, 0x80, 0x02, 0x22, 0xbd, 0x02, 0x0a, 0x0e, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x72, - 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x6d, - 0x61, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, - 0x70, 0x69, 0x6c, 0x65, 0x64, 0x43, 0x68, 0x61, 0x72, 0x73, 0x6d, 0x61, 0x70, 0x12, 0x2e, 0x0a, - 0x10, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x0e, 0x61, - 0x64, 0x64, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3e, 0x0a, - 0x18, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x3a, - 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x57, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x33, 0x0a, - 0x12, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, - 0x11, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x57, 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x73, 0x76, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x14, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x73, 0x76, 0x2a, 0x09, 0x08, 0xc8, 0x01, 0x10, 0x80, 0x80, - 0x80, 0x80, 0x02, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, - 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x44, 0x61, - 0x74, 0x61, 0x2e, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x73, 0x1a, 0x3a, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2a, 0x09, - 0x08, 0xc8, 0x01, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd7, 0x04, 0x0a, 0x0a, 0x4d, 0x6f, - 0x64, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x3f, 0x0a, 0x06, 0x70, 0x69, 0x65, 0x63, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, - 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x50, 0x69, 0x65, 0x63, - 0x65, 0x52, 0x06, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x74, 0x72, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, - 0x54, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0b, 0x74, 0x72, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x46, 0x0a, 0x0f, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, - 0x65, 0x2e, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x0e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, - 0x12, 0x41, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, - 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x4a, 0x0a, 0x11, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x4e, - 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x10, 0x64, - 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x1a, - 0xe6, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x50, 0x69, 0x65, 0x63, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x70, 0x69, 0x65, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x48, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x73, 0x65, - 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, - 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x50, - 0x69, 0x65, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, - 0x4c, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x54, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4e, 0x54, - 0x52, 0x4f, 0x4c, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x45, - 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x59, 0x54, 0x45, 0x10, - 0x06, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x10, 0x05, 0x2a, 0x09, 0x08, - 0xc8, 0x01, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x2a, 0x09, 0x08, 0xc8, 0x01, 0x10, 0x80, 0x80, - 0x80, 0x80, 0x02, 0x42, 0x13, 0x48, 0x03, 0x5a, 0x0f, 0x2e, 0x2f, 0x73, 0x65, 0x6e, 0x74, 0x65, - 0x6e, 0x63, 0x65, 0x70, 0x69, 0x65, 0x63, 0x65, -} - -var ( - file_sentencepiece_model_proto_rawDescOnce sync.Once - file_sentencepiece_model_proto_rawDescData = file_sentencepiece_model_proto_rawDesc -) - -func file_sentencepiece_model_proto_rawDescGZIP() []byte { - file_sentencepiece_model_proto_rawDescOnce.Do(func() { - file_sentencepiece_model_proto_rawDescData = protoimpl.X.CompressGZIP(file_sentencepiece_model_proto_rawDescData) - }) - return file_sentencepiece_model_proto_rawDescData -} - -var file_sentencepiece_model_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_sentencepiece_model_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_sentencepiece_model_proto_goTypes = []interface{}{ - (TrainerSpec_ModelType)(0), // 0: sentencepiece.TrainerSpec.ModelType - (ModelProto_SentencePiece_Type)(0), // 1: sentencepiece.ModelProto.SentencePiece.Type - (*TrainerSpec)(nil), // 2: sentencepiece.TrainerSpec - (*NormalizerSpec)(nil), // 3: sentencepiece.NormalizerSpec - (*SelfTestData)(nil), // 4: sentencepiece.SelfTestData - (*ModelProto)(nil), // 5: sentencepiece.ModelProto - (*SelfTestData_Sample)(nil), // 6: sentencepiece.SelfTestData.Sample - (*ModelProto_SentencePiece)(nil), // 7: sentencepiece.ModelProto.SentencePiece -} -var file_sentencepiece_model_proto_depIdxs = []int32{ - 0, // 0: sentencepiece.TrainerSpec.model_type:type_name -> sentencepiece.TrainerSpec.ModelType - 6, // 1: sentencepiece.SelfTestData.samples:type_name -> sentencepiece.SelfTestData.Sample - 7, // 2: sentencepiece.ModelProto.pieces:type_name -> sentencepiece.ModelProto.SentencePiece - 2, // 3: sentencepiece.ModelProto.trainer_spec:type_name -> sentencepiece.TrainerSpec - 3, // 4: sentencepiece.ModelProto.normalizer_spec:type_name -> sentencepiece.NormalizerSpec - 4, // 5: sentencepiece.ModelProto.self_test_data:type_name -> sentencepiece.SelfTestData - 3, // 6: sentencepiece.ModelProto.denormalizer_spec:type_name -> sentencepiece.NormalizerSpec - 1, // 7: sentencepiece.ModelProto.SentencePiece.type:type_name -> sentencepiece.ModelProto.SentencePiece.Type - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name -} - -func init() { file_sentencepiece_model_proto_init() } -func file_sentencepiece_model_proto_init() { - if File_sentencepiece_model_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_sentencepiece_model_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrainerSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_sentencepiece_model_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NormalizerSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_sentencepiece_model_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SelfTestData); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_sentencepiece_model_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ModelProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_sentencepiece_model_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SelfTestData_Sample); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_sentencepiece_model_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ModelProto_SentencePiece); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_sentencepiece_model_proto_rawDesc, - NumEnums: 2, - NumMessages: 6, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_sentencepiece_model_proto_goTypes, - DependencyIndexes: file_sentencepiece_model_proto_depIdxs, - EnumInfos: file_sentencepiece_model_proto_enumTypes, - MessageInfos: file_sentencepiece_model_proto_msgTypes, - }.Build() - File_sentencepiece_model_proto = out.File - file_sentencepiece_model_proto_rawDesc = nil - file_sentencepiece_model_proto_goTypes = nil - file_sentencepiece_model_proto_depIdxs = nil -} diff --git a/ollama/convert/sentencepiece_model.proto b/ollama/convert/sentencepiece_model.proto deleted file mode 100755 index 5dc02d6..0000000 --- a/ollama/convert/sentencepiece_model.proto +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright 2016 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.! - -syntax = "proto2"; - -// TODO(taku): Needs to use LITE RUNTIME in OSS release. -option optimize_for = LITE_RUNTIME; -option go_package = "./sentencepiece"; - -package sentencepiece; - -// TrainerSpec encodes a various parameters for SentencePiece training. -// Next id: 55 -message TrainerSpec { - /////////////////////////////////////////////////////////////////// - // General parameters - // - // Input corpus files. - // Trainer accepts the following two formats: - // A) Monolingual: plain text, one sentence per line. - // B) Bilingual: TSV, source sentence target sentence - // When bilingual data is passed, shared vocabulary model is built. - // Note that the input file must be raw corpus, not a preprocessed corpus. - // Trainer only loads the first `input_sentence_size` sentences specified - // with this parameter. - repeated string input = 1; - - // Input corpus format: - // "text": one-sentence-per-line text format (default) - // "tsv": sentence freq - optional string input_format = 7; - - // Output model file prefix. - // .model and .vocab are generated. - optional string model_prefix = 2; - - // Model type. only have UNIGRAM now. - enum ModelType { - UNIGRAM = 1; // Unigram language model with dynamic algorithm - BPE = 2; // Byte Pair Encoding - WORD = 3; // Delimitered by whitespace. - CHAR = 4; // tokenizes into character sequence - } - optional ModelType model_type = 3 [default = UNIGRAM]; - - // Vocabulary size. 8k is the default size. - optional int32 vocab_size = 4 [default = 8000]; - - // List of the languages this model can accept. - // Since the model is language-agnostic, this field is used as a reference. - repeated string accept_language = 5; - - // Size of self-test samples, which are encoded in the model file. - optional int32 self_test_sample_size = 6 [default = 0]; - - // Whether to use DP version of sentencepiece. Use it with TSV input format - // (requires precomputed word tab counts to work). - optional bool enable_differential_privacy = 50 [default = false]; - // Set these parameters if you need DP version of sentencepiece. - // std of noise to add. - optional float differential_privacy_noise_level = 51 [default = 0.0]; - // Clipping threshold to apply after adding noise. All the words with - // frequency less than this value are dropped. - optional uint64 differential_privacy_clipping_threshold = 52 [default = 0]; - - /////////////////////////////////////////////////////////////////// - // Training parameters. - // - // Uses characters which cover the corpus with the ratio of `chars_coverage`. - // This parameter determines the set of basic Alphabet of sentence piece. - // 1.0 - `chars_coverage` characters are treated as UNK. - // See also required_chars field. - optional float character_coverage = 10 [default = 0.9995]; - - // Maximum size of sentences the trainer loads from `input` parameter. - // Trainer simply loads the `input` files in sequence. - // It is better to shuffle the input corpus randomly. - optional uint64 input_sentence_size = 11 [default = 0]; - optional bool shuffle_input_sentence = 19 [default = true]; - - // Maximum size of sentences to make seed sentence pieces. - // Extended suffix array is constructed to extract frequent - // sub-strings from the corpus. This uses 20N working space, - // where N is the size of corpus. - optional int32 mining_sentence_size = 12 [deprecated = true]; - - // Maximum size of sentences to train sentence pieces. - optional int32 training_sentence_size = 13 [deprecated = true]; - - // The size of seed sentencepieces. - // `seed_sentencepiece_size` must be larger than `vocab_size`. - optional int32 seed_sentencepiece_size = 14 [default = 1000000]; - - // In every EM sub-iterations, keeps top - // `shrinking_factor` * `current sentencepieces size` with respect to - // the loss of the sentence piece. This value should be smaller than 1.0. - optional float shrinking_factor = 15 [default = 0.75]; - - // The maximum sentence length in byte. The sentences with the length - // larger than `max_sentence_length` is simply ignored. - // Longer input tends to bring the following risks: - // * Overflow during EM training (unigram language model only) - // * Performance drop because of O(n log n) cost in BPE. - optional int32 max_sentence_length = 18 [default = 4192]; - - // Number of threads in the training. - optional int32 num_threads = 16 [default = 16]; - - // Number of EM sub iterations. - optional int32 num_sub_iterations = 17 [default = 2]; - - /////////////////////////////////////////////////////////////////// - // SentencePiece parameters which control the shapes of sentence piece. - // - // Maximum length of sentencepiece. - optional int32 max_sentencepiece_length = 20 [default = 16]; - - // Uses Unicode script to split sentence pieces. - // When `split_by_unicode_script` is true, we do not allow sentence piece to - // include multiple Unicode scripts, e.g. "F1" is not a valid piece. - // Exception: CJ characters (Hiragana/Katakana/Han) are all handled - // as one script type, since Japanese word can consist of multiple scripts. - // This exception is always applied regardless of the accept-language - // parameter. - optional bool split_by_unicode_script = 21 [default = true]; - - // When `split_by_number` is true, put a boundary between number and - // non-number transition. If we want to treat "F1" is one token, set this flag - // to be false. - optional bool split_by_number = 23 [default = true]; - - // Use a white space to split sentence pieces. - // When `split_by_whitespace` is false, we may have the piece containing - // a white space in the middle. e.g., "in_the". - optional bool split_by_whitespace = 22 [default = true]; - - // Adds whitespace symbol (_) as a suffix instead of prefix. e.g., _hello => - // hello_. When `treat_whitespace_as_suffix` is true, - // NormalizerSpec::add_dummy_prefix will add the dummy whitespace to the end - // of sentence. - optional bool treat_whitespace_as_suffix = 24 [default = false]; - - // Allows pieces that only contain whitespaces instead of appearing only as - // prefix or suffix of other pieces. - optional bool allow_whitespace_only_pieces = 26 [default = false]; - - // Split all digits (0-9) into separate pieces. - optional bool split_digits = 25 [default = false]; - - // Defines the pre-tokenization delimiter. - // When specified, no pieces crossing this delimiter is not included - // in the vocab. Then the delimiter string is virtually ignored - // during the training. This field can allows constraints on the vocabulary - // selection. Note that this field is available on unigram mode. - optional string pretokenization_delimiter = 53 [ default = ""]; - - /////////////////////////////////////////////////////////////////// - // Vocabulary management - // - // Defines control symbols used as an indicator to - // change the behavior of the decoder. and are pre-defined. - // We can use this field to encode various meta information, - // including language indicator in multilingual model. - // These symbols are not visible to users, but visible to - // the decoder. Note that when the input sentence contains control symbols, - // they are not treated as one token, but segmented into normal pieces. - // Control symbols must be inserted independently from the segmentation. - repeated string control_symbols = 30; - - // Defines user defined symbols. - // These symbols are added with extremely high score - // so they are always treated as one unique symbol in any context. - // Typical usage of user_defined_symbols is placeholder for named entities. - repeated string user_defined_symbols = 31; - - // Defines required characters. Each UTF8 character in this string is included - // in the character set regardless of character_coverage value. Unlike - // user_defined_symbols, these characters have scores based on the frequency - // on input sentences, and the model can form subwords using characters - // in this field. - optional string required_chars = 36; - - // Decomposes unknown pieces into UTF-8 bytes. - optional bool byte_fallback = 35 [default = false]; - - // When creating the vocabulary file, defines whether or not to additionally - // output the score for each piece. - optional bool vocabulary_output_piece_score = 32 [default = true]; - - // `vocab_size` is treated as hard limit. Crash if - // the model can not produce the vocab of size `vocab_size`, - // When `hard_vocab_limit` is false, vocab_size is treated - // as soft limit. Note that when model_type=char, - // always assumes hard_vocab_limit = false. - optional bool hard_vocab_limit = 33 [default = true]; - - // use all symbols for vocab extraction. This flag is valid - // if model type is either CHAR or WORD - optional bool use_all_vocab = 34 [default = false]; - - /////////////////////////////////////////////////////////////////// - // Reserved special meta tokens. - // * -1 is not used. - // * unk_id must not be -1. - // Id must starts with 0 and be contigous. - optional int32 unk_id = 40 [default = 0]; // - optional int32 bos_id = 41 [default = 1]; // - optional int32 eos_id = 42 [default = 2]; // - optional int32 pad_id = 43 [default = -1]; // (padding) - optional string unk_piece = 45 [default = ""]; - optional string bos_piece = 46 [default = ""]; - optional string eos_piece = 47 [default = ""]; - optional string pad_piece = 48 [default = ""]; - - // Encodes into U+2047 (DOUBLE QUESTION MARK), - // since this character can be useful both for user and - // developer. We can easily figure out that is emitted. - optional string unk_surface = 44 [default = " \xE2\x81\x87 "]; - - // Increase bit depth to allow unigram model training on large - // (>10M sentences) corpora. A Side-effect of enabling this flag - // is increased memory usage. - optional bool train_extremely_large_corpus = 49 [default = false]; - - // Path to a seed sentencepieces file, with one tab-separated - // seed sentencepiece frequency per line. - optional string seed_sentencepieces_file = 54 [default = ""]; - - // Customized extensions: the range of field numbers - // are open to third-party extensions. - extensions 200 to max; -} - -// NormalizerSpec encodes a various parameters for string normalizaiton -message NormalizerSpec { - // name of normalization rule. - optional string name = 1; - - // Pre-compiled normalization rule created by - // Builder::GetPrecompiledCharsMap() or Builder::CompileCharsMap() method. - // Usually this field is set by Builder::GetNormalizerSpec() method. - optional bytes precompiled_charsmap = 2; - - // Adds dummy whitespace at the beginning of text in order to - // treat "world" in "world" and "hello world" in the same way. - optional bool add_dummy_prefix = 3 [default = true]; - - // Removes leading, trailing, and duplicate internal whitespace. - optional bool remove_extra_whitespaces = 4 [default = true]; - - // Replaces whitespace with meta symbol. - // This field must be true to train sentence piece model. - optional bool escape_whitespaces = 5 [default = true]; - - // Custom normalization rule file in TSV format. - // https://github.com/google/sentencepiece/blob/master/doc/normalization.md - // This field is only used in SentencePieceTrainer::Train() method, which - // compiles the rule into the binary rule stored in `precompiled_charsmap`. - optional string normalization_rule_tsv = 6; - - // Customized extensions: the range of field numbers - // are open to third-party extensions. - extensions 200 to max; -} - -// Proto to store samples for self-testing. -message SelfTestData { - message Sample { - optional string input = 1; - optional string expected = 2; - } - repeated Sample samples = 1; - - // Customized extensions: the range of field numbers - // are open to third-party extensions. - extensions 200 to max; -} - -// ModelProto stores model parameters. -// SentencePieceProcessor is supposed to be self-contained. -// All settings/parameters which may change the behavior must be encoded -// in ModelProto. -message ModelProto { - message SentencePiece { - enum Type { - NORMAL = 1; // normal symbol - UNKNOWN = 2; // unknown symbol. only for now. - CONTROL = 3; // control symbols. , , <2ja> etc. - USER_DEFINED = 4; // user defined symbols. - // Typical usage of USER_DEFINED symbol - // is placeholder. - BYTE = 6; // byte symbols. Used when `byte_fallback` is true. - UNUSED = 5; // this piece is not used. - } - optional string piece = 1; // piece must not be empty. - optional float score = 2; - optional Type type = 3 [default = NORMAL]; - - // Customized extensions: the range of field numbers - // are open to third-party extensions. - extensions 200 to max; - } - - // Sentence pieces with scores. - repeated SentencePiece pieces = 1; - - // Spec used to generate this model file. - optional TrainerSpec trainer_spec = 2; - - // Spec for text normalization. - optional NormalizerSpec normalizer_spec = 3; - - // Stores sample input and its expected segmentation to verify the model. - optional SelfTestData self_test_data = 4; - - // Spec for text de-normalization. - optional NormalizerSpec denormalizer_spec = 5; - - // Customized extensions: the range of field numbers - // are open to third-party extensions. - extensions 200 to max; -} diff --git a/ollama/convert/testdata/Meta-Llama-3-8B-Instruct.json b/ollama/convert/testdata/Meta-Llama-3-8B-Instruct.json deleted file mode 100755 index 808826b..0000000 --- a/ollama/convert/testdata/Meta-Llama-3-8B-Instruct.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "general.architecture": "llama", - "general.file_type": "1", - "general.quantization_version": "2", - "llama.block_count": "32", - "llama.context_length": "8192", - "llama.embedding_length": "4096", - "llama.feed_forward_length": "14336", - "llama.rope.dimension_count": "128", - "llama.rope.freq_base": "500000", - "llama.vocab_size": "128256", - "llama.attention.head_count": "32", - "llama.attention.head_count_kv": "8", - "llama.attention.layer_norm_rms_epsilon": "1e-05", - "tokenizer.ggml.model": "gpt2", - "tokenizer.ggml.pre": "llama-bpe", - "tokenizer.ggml.bos_token_id": "128000", - "tokenizer.ggml.eos_token_id": "128009", - "tokenizer.ggml.merges": "d0cbac1fcc9dcf03724b8db5c9bfb593ae1cf68fb9bc72eb1d15274dcbbf618b", - "tokenizer.ggml.token_type": "d70a88809fd7da6f1f028622685cd64268a7a922c5d343c96f25b66327358978", - "tokenizer.ggml.tokens": "765b529dbcbc42dd202ce657341c63807b51f3b07e09898f6aa6196326865d5a", - "token_embd.weight": "b53102a11d9064bbd404833e3464b1b13e08ce73300b442312cccde2f19b2698", - "blk.0.attn_norm.weight": "7318df3cca9e8d153ff0a503026a1265e63d20b2a8c1dd7a2769585082b5d1ee", - "blk.0.ffn_down.weight": "b950806a1fc722c9fad7fd0b20c3c0a7fb50f14395e1e7663a590bfd62e20900", - "blk.0.ffn_gate.weight": "e73e580af6d4f08e060a74a3c25efdf5d3bed99e183d95a5a85ae859014839fd", - "blk.0.ffn_up.weight": "c8158af679ef99746da1befb67eebb19489e0bbe6ce7d97e13e348508244e516", - "blk.0.ffn_norm.weight": "7ec69c3c31e95e49a3359003b0033f6b9e85561a3e3fd83e7476661ecdd756bb", - "blk.0.attn_k.weight": "2732303257bac969b4964e0e32ec08b5a7f5c031bb02bf6ac4467b3ea0ebcf1e", - "blk.0.attn_output.weight": "ecda1d43b4ccc91cd5b366d7e7a275353990ac78561a07c83d9c77031aba12dc", - "blk.0.attn_q.weight": "569b1f5faf92b6f00910cf7effb2d5862f91038ce5c3b0019fc10e5d79fbd5e1", - "blk.0.attn_v.weight": "aa8416c5ef7e32fb54a1f20d6ac651656845d4af240564b397c39bd83e06e3b8", - "blk.1.attn_norm.weight": "03327e02862908c2a44b2f52decdb924bf4201f400b46f8037a9cb2e1d7a61ff", - "blk.1.ffn_down.weight": "5a83a87603f38c99f8e1e370a2d5f967bb45ac51d881a609304a7811027321e0", - "blk.1.ffn_gate.weight": "31da0572c79e655186c721c231376f85e56cdcc6257c28d08c8c5b40d5c22b40", - "blk.1.ffn_up.weight": "e0c811d64ca155c8de10a868e72015d43888834804614ee1aa2953129ffbc90f", - "blk.1.ffn_norm.weight": "5861f313d6137d6f0f904d423df47fffc6069e224ff746e1b637ac9c7f0af862", - "blk.1.attn_k.weight": "5fbbec0acca6457b9416ebdcd90e526885d0224537b7628f6be376a7f275313d", - "blk.1.attn_output.weight": "b237c9763fa3f75166a6f70b70f1566e77d0d89dfa164ed1b3137393e90575c3", - "blk.1.attn_q.weight": "c0a9cf4a98b4882b16f3eb2b49d933793dcc5357abb246fd3fe3134ed2b12e1c", - "blk.1.attn_v.weight": "96867111727200cac1af7865189dd41fd62b47584e5e5f33a91f1d34509cbd40", - "blk.2.attn_norm.weight": "f392f8a88ee3a95b1cc19c40dd4ef66317037b0faaa1800f610779e129ee0539", - "blk.2.ffn_down.weight": "73823eef46632aedcc8c1cb08a736b6aa97ca97842cd1fdfc5567d8dec459662", - "blk.2.ffn_gate.weight": "f4909ae19fc3848b00bb8b9050122e74f8e903b89e22937036f4cc9fea20a718", - "blk.2.ffn_up.weight": "16f4904a3d814ea68f00519724fc4943e48444a84c786bda39aa5efc298a7d84", - "blk.2.ffn_norm.weight": "e3ccdf56e75cb969f6f69c39caf6daf7c4e70e89e25df0f4d2e4bc60e159aafe", - "blk.2.attn_k.weight": "c3beb1e0a11bcf007ef0f0d8f6bdd3082d8b29090cd29597846b5d51e308a8e5", - "blk.2.attn_output.weight": "bb9f66c32cff51154fea92933c2cd62549236f8cb1a767f9ef28d3f99809b343", - "blk.2.attn_q.weight": "8eba394132eef2a05c5a92d62d2376000f7948448d7a2dc74e6b608203add20d", - "blk.2.attn_v.weight": "88f61f77c53567c617db3eef8f30621109a750e679f6784f7911739bd42c2f02", - "blk.3.attn_norm.weight": "7b996675b7ca75fa24107b3ebe0788653ede0f49ac83b8659d71ff54d591f81a", - "blk.3.ffn_down.weight": "2cb332bc05e4821962fdc9dcbcc7cc12630f32117711b687d18fb53c0bc4fbf4", - "blk.3.ffn_gate.weight": "340b387c7f208c8f0a6db904ef8d87c1e84b7d6ad57177abd32d86c8d18b760f", - "blk.3.ffn_up.weight": "07484433f8a7ee061c55aa0de2ecc009f769b0617c9c0ec096e9bb2946df9f0e", - "blk.3.ffn_norm.weight": "4f1a4ade36b393af341240bc894a2aab09cff7e4d56dc4658445deb107f9371b", - "blk.3.attn_k.weight": "483dcd96acb4528df84b9842970994630dbd82b8715ace394aa8b39fcf8d6291", - "blk.3.attn_output.weight": "beaff0810687923585642ee11d929cbf3b43dc6f87f30ddb552c222ab57bdbb3", - "blk.3.attn_q.weight": "0739355002f6fce520863add697e0ff25fc88215322dc3f993be7bb68dcce7e8", - "blk.3.attn_v.weight": "c216d17b6d90ee3e07f82598b8161fae34de2f392dbb0f745b682b578c324767", - "blk.4.attn_norm.weight": "91ab405bc4ba15bf63af233f266aa43aaab43789a9e6596e14a357c2ac7df217", - "blk.4.ffn_down.weight": "620f34ee75cdc73aecb8949af5fbb0d2437fd81422b6d8eb7acfc52addb9fc68", - "blk.4.ffn_gate.weight": "f6feec7bc9acadf35ec22532f8998d8e50f31afedabb19263590dcf8b9a92eee", - "blk.4.ffn_up.weight": "4a72af7cd28fd07b038f6cc4406678d120517280236ea85d9e76eff40ab2cc22", - "blk.4.ffn_norm.weight": "1805b37b44d5d682bdbd2fadeafb763ee001617d7870848cc487079ee34b21f9", - "blk.4.attn_k.weight": "a1e4f9d97cdf4c1b0d177cf00c4e32d1be30c1984a239b3c9bd73f8848888853", - "blk.4.attn_output.weight": "a1547e2497c423b0aff0eee71d9300d6fdf4e4986679418b6e637b69a9a6720b", - "blk.4.attn_q.weight": "0677483a9264ea6803d03d304d87a54632242cb516e8b76b6e3e8284c2f4de04", - "blk.4.attn_v.weight": "02691ba3af344fcc1969428ab0df811ac94aaa2fd91b0dc4ec1ac0a58806980d", - "blk.5.attn_norm.weight": "ba9c028335e5c895b87a5bd1448ca429248f9746ed97bdcb8679923206117156", - "blk.5.ffn_down.weight": "ccfdc9006acad1940a6bc05042a3947f1066acd671e0bb53b7684e9eea9ef5c9", - "blk.5.ffn_gate.weight": "623157679f1e742ccc3807c0b0153ddc8450104de75ec62f1370ec3807c09cf4", - "blk.5.ffn_up.weight": "05748804c65091f963729b58b085f58351891cac8a2861f5eae26b06aa60b2a0", - "blk.5.ffn_norm.weight": "84bae55af2efc8b8429f09056c8c04990c466dae31cb3f9356038b8957f1b406", - "blk.5.attn_k.weight": "8c766180c726b037d587fc52371de6e3307140c52409011609d1225624b6a3eb", - "blk.5.attn_output.weight": "490b582b3b1dc151ae55aee8b6743dad6c01fb49e43afefb6e68394b74be3d73", - "blk.5.attn_q.weight": "6f7b8ca4d9025ec836a44bbcca46be30c66b471a9fb62943ddff8288b3731409", - "blk.5.attn_v.weight": "9f70df3ba00c9e723214b3da83ff435a2163fff5915f75515c9664c05c866c27", - "blk.6.attn_norm.weight": "1a4a66613a682df6f061fc7c4d986f9f7e9175b62f0c42fc1ef31db536bd5942", - "blk.6.ffn_down.weight": "c56f25e4e49b443dbc82d88311ee63bc1f5002cc67e52f4787fd5f003aedeac1", - "blk.6.ffn_gate.weight": "31a5cf1aa9b831a81588d508550f51fc425f9517c43254d4ef7096d38029cf04", - "blk.6.ffn_up.weight": "ce135f3a1163e0c9297a615bdbe68a67ead21edce8debbfa9f6e15e6af8d4c94", - "blk.6.ffn_norm.weight": "4e328ce0648c94e732bc40501858ef6262ad1161e2e407b0cdcf4813fa9d45d8", - "blk.6.attn_k.weight": "1eb1c4c9f9c4c7ff7f5429075e0dc6a7782bed55109fa88df209a817dd8ef960", - "blk.6.attn_output.weight": "3d32986b56873b88655ee1edabdd413fdd9ab18b82108c9ce90bdbc2d3a6f3a3", - "blk.6.attn_q.weight": "8432f583b3a2809c99c393f9beb077cb0534dd5d247c17108f2986cadc6651f6", - "blk.6.attn_v.weight": "5045381513815bb91839dbac8335ffe49bbc7b0008369de7ea97eb676c5e2b36", - "blk.7.attn_norm.weight": "3dabd003638ec2499bfc8a48c49eef34276caab4fe76894eb963207848c2fdaf", - "blk.7.ffn_down.weight": "194fae858608bdcffd235be59ab119d0b91c8549f864ea06dae69249e099935f", - "blk.7.ffn_gate.weight": "00b24c29c30246892bce0791be804a89701d4c1332777e0bcdad5d9d5666604f", - "blk.7.ffn_up.weight": "44d7082a5280080c90cef9e19d410391de34f212ca0736377769b8ddd0c82d5e", - "blk.7.ffn_norm.weight": "21fe8a7fd6911c64e0d15a788b3b4cb6d71dd6ec51de65f760ee89afbb6ae53e", - "blk.7.attn_k.weight": "57a149eec5f6744a9526cd3925ac073f9d12db0fbcb5afe042ef4dc846458c44", - "blk.7.attn_output.weight": "0e9c28a3e81a2880251ce5eed77bcb8be8aaa1a51c9cb6de820b47ed83849fc2", - "blk.7.attn_q.weight": "15ee75263ee4e2a43eb322bc159ae004bb7d77e3a7e63ee4ddab700430693fff", - "blk.7.attn_v.weight": "440aa970bba4bff429fd7b7b1de21f2ad14fb2952b776cfa4acee68d7c6e9b8f", - "blk.8.attn_norm.weight": "af5b44825633c42c1ae964c82bb2be6a242d3a751f0a91f1bae4f593e8f5b6ec", - "blk.8.ffn_down.weight": "b11c14c76adca94fa200496dd2c10743becb23aab6642443ef1ae6d8710edbc1", - "blk.8.ffn_gate.weight": "7bb03d3325bf8637ae2fa1296b0651356515578d46a7c5ca65c7a923d7de27bc", - "blk.8.ffn_up.weight": "b956ef0a0669b5a9c9bf3a8da2d1c24f52d331cfb7354f6d7c51bd65be355e30", - "blk.8.ffn_norm.weight": "c78c3d748302edfef76f71ea5cb2055c94352122eee8b9b1173779a1814d224e", - "blk.8.attn_k.weight": "c0fba6a596ed9c1c32a7055c31a935a8b31e42b77282ee47c1f03ee3bde736b5", - "blk.8.attn_output.weight": "83cf9947080c5d8d571f04a842bc3dcfe7bbb0195fb25b346e22635e8649f2d4", - "blk.8.attn_q.weight": "47409350a576b333d97b7c877d69f47f46df504f3765102dfc0be9e521c7ecd6", - "blk.8.attn_v.weight": "1999dff91404fdcf1ecb34d9eaaaa9244ec7658a74dec8feb7cfd1fddba0347e", - "blk.9.attn_norm.weight": "1e6e29d5c3889ab4e1b0a5b9998cba60179b0f1fca133515df49cbc19d092593", - "blk.9.ffn_down.weight": "acb898a6490adff592e10b4c62d70edc5941661ee6da44658500e9205357c8e9", - "blk.9.ffn_gate.weight": "4cff63013593aadc3ffbaaa6ed70ffdba1224cd43c3644bf6f4162b5ac1ab542", - "blk.9.ffn_up.weight": "f985b5a2d6cf4fe32c7256301c3c89b8ad22b59e516342c52da42d8110766a4e", - "blk.9.ffn_norm.weight": "0d659c538bc6b21ed0018f107ab674a7424a00a42946c80e07208b479b21918f", - "blk.9.attn_k.weight": "f67611d888780d1b38c1c146b361c65310c8183bdf64fd73e2259985c6e8517f", - "blk.9.attn_output.weight": "f12ca1fa62a02ddc3f77f798bfb5707e0c50bf18ee0eaa67025521a98355f26b", - "blk.9.attn_q.weight": "3865185f4361a645b086ad47b72904c095313fb1c624e511647bf1a7dfc1c476", - "blk.9.attn_v.weight": "92125bbfed63544ab56052bd1e4aa453bbf34c795249ee54cde54907c8c6d1d3", - "blk.10.attn_norm.weight": "5d6bfbe545bcc2fcb2fc75c68f64b1f4c918badaf53e0156fe2d88aa977b2f94", - "blk.10.ffn_down.weight": "1dd9da8b0d2696ab5531fbca8a29c7d67567620a9d3e5fc2a19ec5d7e4c6cc8a", - "blk.10.ffn_gate.weight": "6e55e7f014edaebda0ac6819a426221d3b025c27312a2e18cc5806f31e3db226", - "blk.10.ffn_up.weight": "d80dde54af5db51241345ee8d64c1972608644f4deeac1e8195dc423bf27474a", - "blk.10.ffn_norm.weight": "f6ca65951d58ae3379eee8247bec34ebd0db05674cc9295593573841b8a55df3", - "blk.10.attn_k.weight": "b58e350bd6b49aba0fba4e4dd6865de3a2a0651ab865dbf2419b627b53ffc187", - "blk.10.attn_output.weight": "6b26a986e12fe66ec286a21d7d5af5eaa1bfe6f2bf502165d270e4497235a54a", - "blk.10.attn_q.weight": "3440e0e5b7e0d1e426424ae5a33f4e057be623249e9035ea12e57dbe5d3893c4", - "blk.10.attn_v.weight": "ebfadcfe14bcd6dee933053df0a67e12e7a196d5cc45728c1ffb2a2daedd5ca2", - "blk.11.attn_norm.weight": "3ed057b9576cd2de84507ef64c7646dc478c651efca4c2024cbe91a4f3fbf0bc", - "blk.11.ffn_down.weight": "8ff1c2487d22f5c499761e4eb721418f141f960160d0bab779595a34e4d68898", - "blk.11.ffn_gate.weight": "9c74e4507c7e45bf39b7cc7402198cd1dd77e3fff8c625b0413acaeb16efeb9f", - "blk.11.ffn_up.weight": "4367158007161d29939e00a322bb6776016e43f648a94f9b08a96a477aae75be", - "blk.11.ffn_norm.weight": "1cc0288c1491072121f4c9a0af20be0e13af49895696a3320e4fcac608768de3", - "blk.11.attn_k.weight": "066f5b3c144fce1366835e1ebf376f768b333b8ae29f5b478c42d1d0c809c855", - "blk.11.attn_output.weight": "e0d9f3d3f2c54aed59c02713ea4fb562799ddbacbe67ca3998dfc887bc44e47b", - "blk.11.attn_q.weight": "28d3ecc8a88cb3815e89a7f7a7d043da7a71f702b337a126e4d3a2ac1cd6370f", - "blk.11.attn_v.weight": "7c5cdef10ee73bca0a3b9f6ece5f0a0155664e0ce3d8de90ccdccfab5545e5e7", - "blk.12.attn_norm.weight": "973b133301a1af760cd7b3a7955371ea0a750808b442deb6adaf7b98482bd0c6", - "blk.12.ffn_down.weight": "d6c87b4b4ca03f75546ddd6a9e7fca720585a309188723c1ace8122438d4b200", - "blk.12.ffn_gate.weight": "2189a6e0cab1540bd05d6089b922aa8fd694be51255654933c165f302a0c955f", - "blk.12.ffn_up.weight": "5affbec19b58d092b9305721e3552481fe2eff51269ea3ed91cda3b9ef84d4df", - "blk.12.ffn_norm.weight": "f650fd42a34e950f758b4a130e7b8b1a712b1dcbede0291bb8edde47aaed0ef6", - "blk.12.attn_k.weight": "59b1e86f10450a7cc188beefc0856d2dcf44e8d7fdd9cd8859c30ec1ebaf24b6", - "blk.12.attn_output.weight": "446b0d36b2f66bd72a2323f4f4e9d85a0f621e9a58872e89a27248d6b1123238", - "blk.12.attn_q.weight": "3ed6bfd39f040301ed99fad882d3e569769d594259f9948445bef0e44ec881fb", - "blk.12.attn_v.weight": "e73652cd5d0029b1931be3ba9d82508f6696dce5a29d085476a54fb7a2ddbabc", - "blk.13.attn_norm.weight": "491b85278c0bd67bd31b9b8a9720902c244bd067e53a4a03641b7c0994782e82", - "blk.13.ffn_down.weight": "ad71cc248a85e9ced49307a24a9bfae01d387e979a7689c82ff59998e09741f3", - "blk.13.ffn_gate.weight": "0a55984d53971fab97575ee0ef5882013be7fdecfa76e3fbebb5dc85a07a14d4", - "blk.13.ffn_up.weight": "378b697b35e2e53c0de98e8e29b73d42ae3ec112ec16129aa5997a9e2f3b5943", - "blk.13.ffn_norm.weight": "f8aff2f69ab286210fad45a62b03f8d10b38f96a420d7baadf6b95d7b0b0bcd2", - "blk.13.attn_k.weight": "25ceb841afb1034831bea7f4d6a6c578def2ce4d4c412c780ef147dc9a598360", - "blk.13.attn_output.weight": "a242b322889c6bdaa14b67a7bab593db39df8eea3721638ef639abbb74d482e3", - "blk.13.attn_q.weight": "d80be9945a369439e835c55cfb0e97828b8a66bb7ced534d9059c92487bf20a9", - "blk.13.attn_v.weight": "ac33274cf9b67979d9ecdc967a55175afe0c9c4aeeff6391433cd9840c818706", - "blk.14.attn_norm.weight": "12a1e1091de5b2da12c9e7c0b1c8e6f09ce2a749733cf7d5240445b8e21cd093", - "blk.14.ffn_down.weight": "cfd41965c88266e32bc2dcdadda512499c35519e8686fefb9a7f249ab2291eb5", - "blk.14.ffn_gate.weight": "8dcfe774f07a095c7c6cf0a901c9df70d938bad7b5ba347fbc8f694e7603c0d1", - "blk.14.ffn_up.weight": "c7995577fe4a72ea0fb17c4a7b6b87b959072bbfdd5edacc6c367d43465809ae", - "blk.14.ffn_norm.weight": "81c41ebde41739e7016ffec31d2256217b825dc3cae049a935f5f61a60d22003", - "blk.14.attn_k.weight": "fb708bdebe4384f5c4b479c110028554f4d122f166b8091eda7d8d65e6780eb8", - "blk.14.attn_output.weight": "f5295caf2dfdc60553dcabe17537a80577e8b153c902247daac058df23542514", - "blk.14.attn_q.weight": "c12b7a3601c68c63ab5dc9d2599ebf3f3a10abc2c59d3a2126fffd5818f2763b", - "blk.14.attn_v.weight": "1ce968d9149bf0d5e237d52cc6d6433565b4bbf03252a736262bb00a2b34a687", - "blk.15.attn_norm.weight": "266fd2c36d7dcefc6b6bb7f1c9374c41f2bab5d6c84a063b6f91c4f682dad3c4", - "blk.15.ffn_down.weight": "6154886e9ef0a6cc08ab0d264a35f497e6f0987efdac992ed04e87088bea7801", - "blk.15.ffn_gate.weight": "183d9fd3c1b5657840099053d2fd3f72ad953b1de523296159b7761f20491a76", - "blk.15.ffn_up.weight": "51546d4498842ae2340ee226a0888d5f61e7d2ca4d052dfa06a77b0451242d3d", - "blk.15.ffn_norm.weight": "ef7378091a41a25a5f58bf1bf9d3bc64ea562e7f421e1c232b1f177c30fd3500", - "blk.15.attn_k.weight": "8d556ab8d9639324141774999b6eed0e91d7ee645bf3e7a3dcd200b2e7a00751", - "blk.15.attn_output.weight": "54aa6ba87def7cbe18b0c6ab3aff5c351cb3b6ca4a0d7b2cd5f75a1312991429", - "blk.15.attn_q.weight": "10731b0dc031ea8e0ef37bd7f010e0a78518a10a6df05a8bae48e3148b73ef3e", - "blk.15.attn_v.weight": "cbbe50c2ed7224866d3cf9b489c599f3ec41a4ea1aa3181e9f4e87e1fa0cefec", - "blk.16.attn_norm.weight": "387058eb39d4b28c04cf1368247417f1faeae8ae79d894c9f293457e0eaa00b0", - "blk.16.ffn_down.weight": "2cb26ccee585e933401ad5c82ed36ddacb3289efa0b28f8cf91b020ffbd9c333", - "blk.16.ffn_gate.weight": "d745985efb5bab42304e5d509024631efe35f92f2b2ec4931ead6db97ca9727e", - "blk.16.ffn_up.weight": "7a67bd195e0642828ca36eb7818149bb70c2c25f82de07e2b5807c520daf540e", - "blk.16.ffn_norm.weight": "7cefd061c8182482a89272f8a4e88a954b12609a62716923ca1cb3593b1c1651", - "blk.16.attn_k.weight": "d7968a2de67e755b4533e061aaad1cb62f8882af92dcad67f99d6d5112513439", - "blk.16.attn_output.weight": "9e9ab5788272ca3394ea89eadbce8c86ecc3fd75b7899184d6191c134ad9aae0", - "blk.16.attn_q.weight": "ef81c261b536c1a3a093b33f44cf2d42b86e5aa2d821674f07a0c80e992ed925", - "blk.16.attn_v.weight": "aef38e7958301b4a437cbdd2fbae6197f677b09269ec1eaf63188cd5da428d25", - "blk.17.attn_norm.weight": "28f6b289f1bc3131041e9f791b7a2a3a48baee0dfea27bf7051ebbb7ed364d80", - "blk.17.ffn_down.weight": "1a502829aafc6a9bd6bc81f12573bf8632d5c8c659f0dfb13c8b2411f3b1ec05", - "blk.17.ffn_gate.weight": "ddfd8aa0eb98846ebc9afe31366249159f46ae9815199dd70161527ed241ac4d", - "blk.17.ffn_up.weight": "4211a3cc247071bd361b30de2131d02382f552855062bf3b3e004c17992e5d09", - "blk.17.ffn_norm.weight": "647e5fa99a5b0d232af36d15816539f4d27e60a50a341b00aa88bb6e4474f8b9", - "blk.17.attn_k.weight": "d9125ff33a19c502c0f8846433ffc24395048582fc2f463d34a0301a82156f02", - "blk.17.attn_output.weight": "3d64fbb1cfef04444827f37c35fd9ad3413eb2165094d339ef89f00503f09de4", - "blk.17.attn_q.weight": "e5b29424028f578beca385fd82e29f37adedf3037cd51e5889d5a1ffb0428ca7", - "blk.17.attn_v.weight": "1809c5aaf2ac04c5d65539097564ad62796e87d24bb8b9ce5b095561a61d908a", - "blk.18.attn_norm.weight": "99daca58d001c627523d3adfbca1d95f04e590382a326866544d57989d5f4835", - "blk.18.ffn_down.weight": "84f30231ce6ca0f10227541dfc602d6418c1a210386b0c4926ef1656e7d4635c", - "blk.18.ffn_gate.weight": "ca5bbe4468b541740e54f69b9e08fcc8e478c344b70551dab21b1206acfbaadb", - "blk.18.ffn_up.weight": "0b3067b9dded31686dcfdc1e247eae3974a28a61ac59e9862758dbfaad64e8f7", - "blk.18.ffn_norm.weight": "8154a102232dbc0f90ce77ae5c1ff8f26f8b6e4dcf326e9ec1645749669e7960", - "blk.18.attn_k.weight": "25abb26021ccc481471a30e0d4cbeb7e1db29828417ec5136edeb93fecf09ac4", - "blk.18.attn_output.weight": "d87d481d9b046b68efa06ccdd4ed8cbf61e692d61114b75b7fad5ed75f5d87b2", - "blk.18.attn_q.weight": "cc6400379e15766992ff1293be79dc67682c28e9e15155a78109f4b64653b164", - "blk.18.attn_v.weight": "45c75cb1dd496aea3173aafe2575b841dd1d02cbe010b3198099731eb98f531c", - "blk.19.attn_norm.weight": "65389efc75297684773284ef8e5f8789a4504b636c9f33b8a32e0ee42499fa72", - "blk.19.ffn_down.weight": "4eefab7e939f64a17e4a214ca3c77a6fa110d94f677e2d6401086f70fc538b04", - "blk.19.ffn_gate.weight": "f1c0a59cafda66f466ab585b0b8b4861b58abe87a67cea1f6a488492242edfdf", - "blk.19.ffn_up.weight": "c42d045eef588db4a0e56960a57e110e1ff92eb8041107d19899165fd3b90f17", - "blk.19.ffn_norm.weight": "a8f33eda6d5d62ff5f333ad9771783caff556641f4e7df713451385676f441fa", - "blk.19.attn_k.weight": "0bab5d9e9083492bfb05a5a3bb23b79c0e7b99ef6a6644817b4d57d5c453b8a5", - "blk.19.attn_output.weight": "c99c551d70eafad0f7aea98fb6f9251635897168eb3895f76abf0d4ea3b3aa6f", - "blk.19.attn_q.weight": "c98bde95627c3b54c9443813ca50b4e14f518319681db6bbf7b2332ba26e9a60", - "blk.19.attn_v.weight": "ff3a490518cf64904db89ce0dc7d6eb89e870f1440e41883c6b55a221f82de84", - "blk.20.ffn_gate.weight": "761f0e317229cafe9d3754048ab038a0a84e9a287b196ab65f633139f2d29aba", - "blk.20.attn_k.weight": "45d13439b41066d282e8490a726785abf513605f46c79bd0c840f6419d27e790", - "blk.20.attn_output.weight": "a3b958d84b4a097844179b7d55c18fd0e4f319cb15e918c6fde33b68de1bcac6", - "blk.20.attn_q.weight": "127ab8e7d8c3f882874904196a02712bab42e6744fde45871b67350609d19f5e", - "blk.20.attn_v.weight": "5f0ad2d14a8ae42dd3bbeccfb33295687a14055fa92c54bc946249373c1c9f17", - "blk.20.attn_norm.weight": "77300b1755edc8c70089e0f45efa646056b9add7d8568b2324d2f3e62b64971a", - "blk.20.ffn_down.weight": "ab93d0e075b42e9017b701a070d561e698050d90aac4b4b9919256fbe50c3204", - "blk.20.ffn_up.weight": "4fd6628a07acc57a48d1ef83f81b7d7aa0bce569c1160a99d307284f8821322c", - "blk.20.ffn_norm.weight": "2a9e46b9e48e8e55215de56592e1f189530037c1c94a1428e3d6f106c7f26fb2", - "blk.21.attn_norm.weight": "4b3b5912c7bc61eb9da8e47d4651f896e85d9e59c4ecaa65df7acf3c21737298", - "blk.21.ffn_down.weight": "7146f931663d93b8771cd84405cd4802ea6560d0729b0d6d44588203c095bc53", - "blk.21.ffn_gate.weight": "b44ec5d64388fa40b90b3e9976d97a8b6800fa3b97584f32e64b03daffb8601f", - "blk.21.ffn_up.weight": "0cf3643fd23c685e17062cd11e116e17ce57a405e5e78953bab94cd62fe48789", - "blk.21.ffn_norm.weight": "4ef2cdb53da166df70b39f3e6b17af51848cfa5ea3c27ad6a1ae2a1bb1da1ce9", - "blk.21.attn_k.weight": "5d40f32a706f670c19972b14176bf660d5b045e3637b110dbf8d7de4ff32101a", - "blk.21.attn_output.weight": "18afaa916752ce16c9653ec0ec7e2fe60be55faa2aa5025d147be184adb75cac", - "blk.21.attn_q.weight": "2621daa5f858931514a4b2f0fe8d81cf9b96f541e6af99bfa7539e9bde8e34ee", - "blk.21.attn_v.weight": "63226dafc54c899bbce4aa49efceeedd8908e94faa613450fdda91f332b62864", - "blk.22.attn_norm.weight": "cf3058daab4d2c04387e7d169d1553bb8e7358eea66285ec067703f6ce62043a", - "blk.22.ffn_down.weight": "6a58d5fd220abdbac6cee7ba048abab794731af318f04982c2506df59413d0b3", - "blk.22.ffn_gate.weight": "d5614535324b03c7b91727a903b2a72f8d07ad17f7aa8b61ea173cf9b895069e", - "blk.22.ffn_up.weight": "ec20da3949566e93f66cabb67f8cd7eab399047ec6ebf5d43edfaf3669b82296", - "blk.22.ffn_norm.weight": "84c82f38f53a649972a44466fc476bf764e064ce18de870291edc302f3700e28", - "blk.22.attn_k.weight": "a3d2ecc37fde7c201176bb8abadf27f0d8ede9679a6034913e03d9db924fda12", - "blk.22.attn_output.weight": "5a3b8bb433f43a387df43dd371bdf80ddfac986dfeaf38e9bac1d7a0ec6628de", - "blk.22.attn_q.weight": "3a875cec661b4859f30a8fd2c866811184b25b68c9e36fe2663d299caf8b59c6", - "blk.22.attn_v.weight": "8717a83b79035058dcfd3ef6f8e5b36e71d77379e5a239e1899eef8766fb7703", - "blk.23.attn_norm.weight": "2b4a68a0a2f023dd646e4755c9bef17c2f631901154afd839edac7ac006ec99c", - "blk.23.ffn_down.weight": "29499b1586c6fc4883c9b7a9c8cf388035146b5aecf90c5c4c8c8e082c71e7d7", - "blk.23.ffn_gate.weight": "7d6554036d21c587b9b556428054f9c15cbef96d24b257f906fcef4ae38bd9c8", - "blk.23.ffn_up.weight": "19761ecb288d6ebd44b681c4535661583b1e19dc29e96d0c007333cd8f00aacf", - "blk.23.ffn_norm.weight": "37dc35500790a4ca33807b39cf7af65065e535dc25b9e94f3ed2759f61887ac9", - "blk.23.attn_k.weight": "717547d00323817b0cb40a72ec5f8cf42ecd1f9e3e42715c2cc5e38f07fffffe", - "blk.23.attn_output.weight": "a24786feb6a905fdf166d7500133757cbe494779d4ebcba9eb03046b319557df", - "blk.23.attn_q.weight": "6a2c4a98f138b928d22136efa163562691d3b4ed526d52d46a2fa2694a8f3965", - "blk.23.attn_v.weight": "c6e6081eb9c38a7fda023085957b460e9ea321e1fff408b38c2b58595c39979c", - "blk.24.attn_norm.weight": "5e6283f891e538670425f3e244b08dc6f96f33dfa4aefa913f8eb17212421850", - "blk.24.ffn_down.weight": "e09eb170f389deea0a4a1cbfdb52c12490768a2c60491b7bef8a4c445e2a08f5", - "blk.24.ffn_gate.weight": "af29d815cf49a38fc2ebd0bf9b2dd9933d023a29f2d766981acb9a1b53f09117", - "blk.24.ffn_up.weight": "36ccd9333426666de9d3088bd4dcdf5b624b09dca9e3a83a22fc0383f2d950fa", - "blk.24.ffn_norm.weight": "a88e1692318826db6ac42582d182e51a3c698c655d0e21e04fa086318832d07b", - "blk.24.attn_k.weight": "f7d61d6d1225289bcc502e3bbb0168b4584add0253218c1b77ac92ccef9a1c2e", - "blk.24.attn_output.weight": "85a1363b3ccc87312094c2195022687c16b0dad7fafb9e80bb4ec474d53c29ac", - "blk.24.attn_q.weight": "53482a2c008f42f4fad779ca323addc3712040149dfc12f782417756388a72bb", - "blk.24.attn_v.weight": "67498272369af7dd10097c73b07f731b565cfc9a559e711cc0d526389e7b44e2", - "blk.25.attn_norm.weight": "98dd617def5cb7825ee4833132ca2da2121245921585e1d9e36b93344adc321b", - "blk.25.ffn_down.weight": "7fd477d6c50aed5f424a878dd284343379cffbee8a34c0b6e55100c8305fa13f", - "blk.25.ffn_gate.weight": "f892c9806c8ec22e8aa746734ac9213428c534921cf161239e1d249fdb5d1ec0", - "blk.25.ffn_up.weight": "528bed14c9bf9762f790525ee40412545221f4321d2a2323fa8e73c58b7643c5", - "blk.25.ffn_norm.weight": "ca5831966672e7be6a578feeb631ec3570d3b5afe12860819ccb96e896ffc346", - "blk.25.attn_k.weight": "610d3068cc9b20401f0c3a0efea39a279dd9f564fde19baf3403b2ec2319e4c4", - "blk.25.attn_output.weight": "798aaf702e53b657265ac3b5e6caf3a0ab515bdadfeb1a3a156b4f3bfba76666", - "blk.25.attn_q.weight": "8a7fa25248de83029fb97b51d036a01baebe31fcb4be121ab00dd8b7de209b10", - "blk.25.attn_v.weight": "2a53d5e9f8a1218c66958c6388d3b37400a9af7956c785024ca44bfbc3c7d371", - "blk.26.attn_norm.weight": "5f44fc043481eb0771f3e6d2420bcbcf73140afb9a9feb8eddb6575452acebee", - "blk.26.ffn_down.weight": "944a60a409d0d5b6a851e33c69aca152454b691711a8b96f5bcc488772ab2833", - "blk.26.ffn_gate.weight": "2a0ca4abb3de5593e6693d8be69b63d6d1a639855ac8332a75f520353f030c62", - "blk.26.ffn_up.weight": "0b1df496163f9ac07bf89375d3eb441b51a81d41b47d769a04a61efc18dbe35b", - "blk.26.ffn_norm.weight": "56b8dd046e9be6ea71f7efd80dbd14e7fb1aa020d3cd38e063275f3873fd12f8", - "blk.26.attn_k.weight": "b1dabfabb970e6971c7ea6e53c63cf7ef56341e6a2edd9cf177785cad9af2f9a", - "blk.26.attn_output.weight": "39532c7e836baad164a655fb97ec5114ea4da37ffba9fdea2684f6e4450e6f84", - "blk.26.attn_q.weight": "8f48bf6aaa1252bc149e98af2be1777a5c0d2c3274c6d314171ea9344a41b604", - "blk.26.attn_v.weight": "02fb145f7fd905133750e90571effacadddfd3f4966552dc59982ac3900ab8c4", - "blk.27.attn_norm.weight": "654d168fc3cab716d91261f5719f180b7d697218401633b4878a759f1b5283f2", - "blk.27.ffn_down.weight": "2823272bec3a1c12f02cc4cb24aa4031abd7e9dbe0b02676e2305b21671818f0", - "blk.27.ffn_gate.weight": "b1a1d40cd02f97182cac17a79971d1934ee0daf3aa0bf11303568c636e208a64", - "blk.27.ffn_up.weight": "ed62ec72a020d070e64eb7b50237b32213944727b5b2427f45d989f50df5fb2a", - "blk.27.ffn_norm.weight": "c69649ac65d694b306a905dee8b03b89eec1ed188b1eaaf38f8e29d4b12e38a0", - "blk.27.attn_k.weight": "cc57bbf413f1fd227128dc66efc8590c73634cbd6f96d01ec4878b5e7ca6a925", - "blk.27.attn_output.weight": "cac407ad02361d53207b3c7e25ceab84dcb4347b8087055162e2efe14d11d84a", - "blk.27.attn_q.weight": "0af18e07cee12015761c07c94407024f4f4d77d97bdb24163db0e16669e2cef3", - "blk.27.attn_v.weight": "a1d08fbdfa40af773c5adcf93bd68b78a44ed144e3fc6bbeb8af02e937527eb6", - "blk.28.attn_norm.weight": "f39a51f814512b040a1082143150e4a49ff730f85cef49d7f77fc79d83e91f40", - "blk.28.ffn_down.weight": "74f29ed51055d1c1adb8f0660bbe538a27e016c65650f2d67efc6f1c84fa1b45", - "blk.28.ffn_gate.weight": "ae48bb16487ded6781c60aafc0bf738fb4ae15729952906f247d216592ce249a", - "blk.28.ffn_up.weight": "543009727718ac22f11ee4b17815f68ea6f15ba1f3e7ed5ecdb755cf6417565b", - "blk.28.ffn_norm.weight": "b8f9e54c322079ff20a82b88948cdc2916c22c7db40b9a9ed6d3cbe89efb727e", - "blk.28.attn_k.weight": "55d055ba653b728d6e784f9e013786fed07115c9fdf23367e3941386d5e77db8", - "blk.28.attn_output.weight": "155101c03ddbf18f4fd0694bfc982f33c7bae25c9b087d6f5273c2bfbffcf2c9", - "blk.28.attn_q.weight": "1ed19bfdd22e9c14eca014739982492e9516d411515a8585f65cf754d849e53f", - "blk.28.attn_v.weight": "11ba854dd575c025d37256eee9041f6d1bd2b549a083d6409a09bfc1542913f3", - "blk.29.attn_norm.weight": "02b0bf5e2fcefd11a153cc988c81ba672682e4844fcf6442423e21a0e10d566d", - "blk.29.ffn_down.weight": "594bb692ec2779938721ff4748666ca8370e0e4fe85229503f616438b8884f5f", - "blk.29.ffn_gate.weight": "8bedcf47e91dcb2cf4093de56b048ee411faab6ff472f89ab2c9c113a08e6967", - "blk.29.ffn_up.weight": "e241a547b5fd6dfca8200b8141e21c1c487a96cbc4e5855f181a7ed1be91b642", - "blk.29.ffn_norm.weight": "e63eba5e4c6b288bfd9f15e46e236086456c8b7f1f9c732c0b5de84962a2e7cc", - "blk.29.attn_k.weight": "afe5979d5bcf211aebb526620f5974bcb0a2c39c8be71e815575c55d6385e3aa", - "blk.29.attn_output.weight": "9c944ed44b124b014906fc240afd3b90aed56bbd9567f2eddfd5b7a685b3cb48", - "blk.29.attn_q.weight": "e234e08e5c1bd9245a2edc8d63e9933b6b879f97c01392209cad4f55f05f3ada", - "blk.29.attn_v.weight": "5cb8e3e5f954e775c5a5e4de7a9a62b17e9c6931bb0ff0e2f82c4126fd3e1a1c", - "blk.30.attn_norm.weight": "a65483ee51a0b214144ec8a14f28ea5437586e9e12ebe342a57d1f8627ee12af", - "blk.30.ffn_down.weight": "417959da77ceb33ead4271cbb9428b195196173a893c44e52880a7ec61b4856b", - "blk.30.ffn_gate.weight": "a0d503ffcbe45dc927600bb98c9f6082487e65cb577ab545add400d666a87638", - "blk.30.ffn_up.weight": "f8ab957b82ffcd10b21303cb5e866209b6fe95f827b1b94e9a949207952d12c0", - "blk.30.ffn_norm.weight": "210c7ceb0514a9ef27b5d4d1b3aff6dde43f1af0345a050d71097940e0e73e03", - "blk.30.attn_k.weight": "16861b9abcf5a3fe73c93d977ca45a1e6daa65be0fd85c2cff53486ce2033afa", - "blk.30.attn_output.weight": "ca541fb2e57e2257118c35784845b0c731278af8db3036ac53d71aa1681fdbdc", - "blk.30.attn_q.weight": "f7834917748e26bb456b945e230bc926c228e93696bc01fbc2b134bdeeac71a1", - "blk.30.attn_v.weight": "9292783171dbe5eb689d17c9bda11e537f0e9b328fced6986c938d61ed590e81", - "blk.31.ffn_gate.weight": "e4766a04bcd8f937ba883c6a144101e546747804ca66c35c97281d6ccb47b566", - "blk.31.ffn_up.weight": "cc1e666116f7e6b06736db4aa4b81003c583f54f4d9200bfa48842249940e16a", - "blk.31.attn_k.weight": "fc80b57557687504efae7d24265cb7dc39b8f826bb3d897a11783012dbedc44f", - "blk.31.attn_output.weight": "215617f50a1f5d9b2250b82f3652b35a9e9aa0ad9ef2b485d73965a14b2b872a", - "blk.31.attn_q.weight": "274b4f1dfb0bdec28632705677049fb3e327ce6d9e1f3baaad1560439039982f", - "blk.31.attn_v.weight": "e641b8b926f9dfcbbf6b6da1c02555525ac4b1c306d96f20cfbba7d6662c4e56", - "blk.31.attn_norm.weight": "b3243c361d4041ddb892ce6862dd5091f57d87357e3c67e177451b85d8baf34d", - "blk.31.ffn_down.weight": "0a00cd3ecd5e91624a27f9e239b1de425d5ba3cfff82c256a11a4ad434abf3c2", - "blk.31.ffn_norm.weight": "2a0d67ea2bb1303975712243f07273c92fce83baa11b1cd6d8e42e74ea3c810b", - "output.weight": "768615f077fb797967844571c58b94d7c399d884d115be3ab4b0154504cae892", - "output_norm.weight": "7cc5b7ce10e5082000fa00bfa68af8c7c5da218e59e2c41cf2f1499d40ca229e" -} diff --git a/ollama/convert/testdata/Mistral-7B-Instruct-v0.2.json b/ollama/convert/testdata/Mistral-7B-Instruct-v0.2.json deleted file mode 100755 index 88d447b..0000000 --- a/ollama/convert/testdata/Mistral-7B-Instruct-v0.2.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "general.architecture": "llama", - "general.file_type": "1", - "general.quantization_version": "2", - "llama.block_count": "32", - "llama.context_length": "32768", - "llama.embedding_length": "4096", - "llama.feed_forward_length": "14336", - "llama.attention.head_count": "32", - "llama.attention.head_count_kv": "8", - "llama.attention.layer_norm_rms_epsilon": "1e-05", - "llama.rope.dimension_count": "128", - "tokenizer.ggml.model": "llama", - "tokenizer.ggml.add_bos_token": "true", - "tokenizer.ggml.add_eos_token": "false", - "tokenizer.ggml.bos_token_id": "1", - "tokenizer.ggml.eos_token_id": "2", - "tokenizer.ggml.unknown_token_id": "0", - "tokenizer.ggml.scores": "e3d3eea80bb41a1213f2d0aa3e8a38581d1f19323be77dbd779c9c7e3b72e676", - "tokenizer.ggml.token_type": "6040635e6bd38d98af06698feb75c1802bad35180ee6ae0a503e38c0f60fd71e", - "tokenizer.ggml.tokens": "604ac4bfbd019e430d7b6cdf18c6c0cd5b967900601f0307f714ec7773aa5ca6", - "token_embd.weight": "cde834ccac5e94324b25cb81b02d27312cac0c551b55a7e1d555d90bf6cb6e81", - "blk.0.attn_k.weight": "458bfdd9715c66e017c2447b1ed3c582963a3111479314e664faad8c914f42be", - "blk.0.attn_norm.weight": "e1fd60b95f713bae7b7e3ca933c64ae6c9cd1e8d808000204bbfdc19f0ba635b", - "blk.0.attn_output.weight": "df13b6a157d9d4f96c53b012b3b9bcd207d0c94144cbd22ae3ec13bb07d6c373", - "blk.0.attn_q.weight": "13b4126b4245bf06c915a93317c42b8174e05053535ec99dc576541e4cec7c25", - "blk.0.attn_v.weight": "5b1781d3a341214511b27eb4e268674ea3ea829dbdf8ae5a6bb89b3c0b33fafd", - "blk.0.ffn_down.weight": "49186f5d8148d316b07458841d13a2e66587f4af69b776188a809591ed9c070d", - "blk.0.ffn_gate.weight": "4397e30ece09136f00f4ff84ff49e5241b765a374deb8c5a12e897e2bf73473e", - "blk.0.ffn_norm.weight": "43260589aac3850a779bca3f9649f793bbfbe5db538361cb743b3830217f8287", - "blk.0.ffn_up.weight": "fd7ac918240a07566f6967527ffca58fcf433a30b78fdd6d84b2136d4ebd9987", - "blk.1.attn_k.weight": "209839566c7d235bdc20565a4766378b6ee8553133a5a3315abe8a85baa80712", - "blk.1.attn_norm.weight": "58c52986f7c69784ba327cb7f350923420782bee17fa39b1fbd13839d4005357", - "blk.1.attn_output.weight": "5067cc628449682665dfcf59b16e58fe2a9d2a81cb099f0fcd42f4f8670c6740", - "blk.1.attn_q.weight": "f410f9f0dd5edc09401af597d02e2a4c727f1502ec3ec3898321617b36c6df6b", - "blk.1.attn_v.weight": "d40fa49e07c102c0644e130e7909eaa93ed0d54e2edddc0759e721d58a4e4f5e", - "blk.1.ffn_down.weight": "594b1eff6ed4defbdd819fabbe2d48764984f08878a860bdb808511d5a25b8db", - "blk.1.ffn_gate.weight": "4cda97541e388a5bb607ce4cc8b3db1da7045830a630e7ba4d17807befcff346", - "blk.1.ffn_norm.weight": "66c13d7481be65b97aa474735ddc9674f33d512ddda76fa6fb45c7464b09f1ed", - "blk.1.ffn_up.weight": "1adc6de288ba4cc1237833ca8b4eb81107149842e38bc452e18e5cfe284338a2", - "blk.2.attn_k.weight": "5420423559f236ab22d85a00849f31e0cc6e9c7dd879de724393d8cd2b379153", - "blk.2.attn_norm.weight": "495fe1ab40cc52aa054ddd4f0c2d2790f4326c8d103296b1b38f3b1060db2a24", - "blk.2.attn_output.weight": "ccb83e7085381f558bfd65588c525ad2671feddcbc3887afb4038ad9c7aac348", - "blk.2.attn_q.weight": "2e8f77478392bc93c2a391f2e0f4a173a952bbab88a7aca099c6ee909726409a", - "blk.2.attn_v.weight": "d64512590f3b7ebbb9e77c2eb97fbda90b00d45c944f2b174f03a2cb11007567", - "blk.2.ffn_down.weight": "1de5084a05dcaa6b1bd926e83517dbe9ebe7fde79235fe56018b3028b1aa6397", - "blk.2.ffn_gate.weight": "cbea526b557f49aad8c976973cf367fcd12175b900f551984f498b9e07e4b7fd", - "blk.2.ffn_norm.weight": "530aa49b10c7eae08899d143409240deb95dae4e1d5bf78cea3b26393cff3ba1", - "blk.2.ffn_up.weight": "13a5fc19b96b4dcc1e9bd01998c8272ebe52034c1933ed123a506b711fae9a5c", - "blk.3.attn_k.weight": "1913b63a73305941d8cdc472e7f101c633d3357a78602eac0a4b49a744261075", - "blk.3.attn_norm.weight": "9c11bed5ab41f4adbfdae4ead65b525c8f19443e656a8c61ba412a4e1ad1193b", - "blk.3.attn_output.weight": "bb0b42c1d34779c5943272ed71f1dbb31ad8edd75f8bcd5c868f88505ac3a610", - "blk.3.attn_q.weight": "3461a1fe4e49f5319ea047cae98ccdb46528a3ec23831183fe87610b48c94948", - "blk.3.attn_v.weight": "82aa30be6a61526a41fb79bb28a2617416f5909f0477aa9e95e16be9370fcb38", - "blk.3.ffn_down.weight": "68521011ae03f5e3b0966127111afa8ee9f2eaeeef8d3a0b86b633e0332e9fbf", - "blk.3.ffn_gate.weight": "1e89e26338fd364bb679695968c65106382f15ad55c95cbb5ec9bdfeb766f432", - "blk.3.ffn_norm.weight": "c81932529a5a8c417c27b888dbe95fff8b447c2ea5f6f560444ec5d50b93832c", - "blk.3.ffn_up.weight": "305021735afd8669afefd713f56137248d5e817e60471a112ad06b7fa07ffe88", - "blk.4.attn_k.weight": "cc26ba5c5c28082a79e6abfe61186029e80b145252ca6a7924c437f0bcf2d51b", - "blk.4.attn_norm.weight": "302d251fdcc91f7468cf33f80b49484251d8917d7018ad264ab3a85c8ecf9ddd", - "blk.4.attn_output.weight": "a012f5bee3520cd4ce51f0076c132ebc3653309f304032ad051aa308f55f36de", - "blk.4.attn_q.weight": "3c8d607e447f5ef21e73af71e3c0d32fae16f91f31faae34ff06912cf9cb68fa", - "blk.4.attn_v.weight": "49f6c81a634ce46d71c2350206ecbd231b1732af96e4e4e67693c41a07e007d8", - "blk.4.ffn_down.weight": "e89504f311a4a34dc819a67b761022f14d71c43df3ead4f892c87aaa8e9f0adf", - "blk.4.ffn_gate.weight": "18b22f079a2fbaefe3572eec61fdcd996fd747724e2f0ff4f08cfcb43eb7bfb6", - "blk.4.ffn_norm.weight": "22415a492c168a0878912b05c854a631228b01c3ea8842e1d75989ec46c18a65", - "blk.4.ffn_up.weight": "f57379eae2874d8853f14ddf0f0fcc4ff1338574d5ed5d7e88331d5fb84f5642", - "blk.5.attn_k.weight": "d627af853c40bddf9762ce3988008c1ff17f2686fa8f73a0b5da38010147c316", - "blk.5.attn_norm.weight": "9ce01092c7f7f1c3ef72d6b794da12d77aa1f6a24fb96ba1b9bd5a0bcc3e2443", - "blk.5.attn_output.weight": "0388da8064c4b6b795ce2d8079e8a36535e82b2c9cf794e38ce8ae460aae726d", - "blk.5.attn_q.weight": "039b7ce1c909761fdf475c06cf14cabe5a90199282c89e4dcf460e95a4b6275d", - "blk.5.attn_v.weight": "c47bfd8d2496bdb6e00e03b903e15fd0ee806a515094ec257e43cc433147ab7e", - "blk.5.ffn_down.weight": "1d62e6708974bae318cbf00a8bf621d9ba0537e549ce4710a536520a8d14168e", - "blk.5.ffn_gate.weight": "8b42b1b11c92db19985094cbb50434e3a7c9cfea71ee6f21ea79eae7c49284a5", - "blk.5.ffn_norm.weight": "e0bc520f1505e687ec391d632a381d38d8ebcdec19f614a11a2000ab573e8b7b", - "blk.5.ffn_up.weight": "8cdcd17d2ea89bb9ab902dbc6bf3f827fa4ee029c6bf19eecbdefd146d8b6f2f", - "blk.6.attn_k.weight": "5dc6bcff89794d1756bf57ec665b58622d9352130d31082a6c66e1a079f99932", - "blk.6.attn_norm.weight": "13b26008abe0f119b5104b9d78ebd5e797d3cdd68122b93d73a3b4831a54d085", - "blk.6.attn_output.weight": "f5a49917ea70c3fb311ccfffbfafa63ab18416a5d55e5429b70ce8bfba57c075", - "blk.6.attn_q.weight": "d9c2f652c87dbd09ec3822e12876648fa32e86553ac25afab723b1cd9f8cef90", - "blk.6.attn_v.weight": "5ecc5fe67609a35151011cb526f45c56fc0a999079ae0ff37c755ca03c68c555", - "blk.6.ffn_down.weight": "0ec125ae0ecb2d9277fdb1b04f17efee94e37d0ae37311057c212ca2db3fe6d1", - "blk.6.ffn_gate.weight": "fa4d6d38355ee8aa3b80b476d65ae7e343c9b7770d7b097fc848ee8a6e091d1f", - "blk.6.ffn_norm.weight": "30e8f7defc627532e1739dc76d31223d45767391a431f925b63dabe334b0f392", - "blk.6.ffn_up.weight": "6b97cc32b290fa9087806b5d65aa6dc1760737730c8c71394cc4f30c2157f9ab", - "blk.7.attn_k.weight": "0231cb127cb7c3714cd72b8f39343891d7715a9bab2237ade9e7bc5f4ed2e68a", - "blk.7.attn_norm.weight": "7c3187f07eead7d219d98ab2daf87905e88d5f1ace109b6f5fa55dce3914981f", - "blk.7.attn_output.weight": "2f30ad972c284ae7c8eb0482053433495ebe8fe9c5ee2c28b4bc4ed1f33050fe", - "blk.7.attn_q.weight": "3a2b4b8d61cc9956d304fa9f82a9e65b4bb9fda2196670b16df7e0d8c43eff2c", - "blk.7.attn_v.weight": "d2aab97d0dcf0f61dd2f32848f7a8a99c423a4948a660a660a03a546972b8db8", - "blk.7.ffn_down.weight": "2270d520468c5549cd30023ff9c452a277058310104c4239a616373fc5a94387", - "blk.7.ffn_gate.weight": "4134a3ef71b3eac8f76b6f1a2e58625b3bae48081f175994bc3ed7d8b0d4f2d0", - "blk.7.ffn_norm.weight": "42df4abd4b8769b16f3930068f96960af1b061f1aeb7505384f272233b2badff", - "blk.7.ffn_up.weight": "c920549054ec16ff8c73a72f5d837cf4e11885e44db57c1c1c584c18fbd7a9a5", - "blk.8.attn_k.weight": "01c609bd3bf31ce65688f1f640ee413740e821330134d4ed1877a3065d1527d5", - "blk.8.attn_norm.weight": "48857411f769b00290f4e4f2e593e092781fdc2503f80c1e3eeda1b85a20f74d", - "blk.8.attn_output.weight": "90fb273f8df83744554bd59236515c16c5a5a698ca3fbedc17cc89ddcee354ff", - "blk.8.attn_q.weight": "ade617ac4653c7f00593dbb51837a468afef20a14eaab3780fb96ac3d6714369", - "blk.8.attn_v.weight": "c2c37496494864fee5c527d1fe1f88529d31c73f9cbd02ef9b2e9b23611ea50f", - "blk.8.ffn_down.weight": "2da58572e9ad79087c03cbb0c23c9ef69f93ec221fd5fe4ed92fb93871d23ffa", - "blk.8.ffn_gate.weight": "4483294e628edaa4901708e73e92c917bdd93b780fa01aa74aed57166f2bbf0a", - "blk.8.ffn_norm.weight": "c0cbb7a4f8123b62f0c4652a687f3b394802bc32870dc446eefb709e42043a7f", - "blk.8.ffn_up.weight": "9eaf8a2060cb9224cd585997cd671866c4051ad885c2c6d9fdc7056c2a5c0d89", - "blk.9.attn_k.weight": "5dd36c45fbc9c50fd35c36cd75576288506971eac5c5311d4f5c16ef60099645", - "blk.9.attn_norm.weight": "3c8ca64f2f75ed7c8fc1da010c23be787648139a96ca0ef3ad10be7b14942b8d", - "blk.9.attn_output.weight": "6277e1f833024f53c409be919ec76d34464a78b278c8f9dbf79e777746e3b995", - "blk.9.attn_q.weight": "87352b70d9e328c2d51d59090cf5ea5a046529864a890d0bc8986447a0a5c006", - "blk.9.attn_v.weight": "2efdf01161d7a82a9117cc2d87d37dba5ffefcf730781cb94fcc95130e48ff9e", - "blk.9.ffn_down.weight": "e7658a2ca984961c7ace16acb679387bedb1fef656b5330bbbf588db19673a75", - "blk.9.ffn_gate.weight": "773cd330d4ff5d64be8af00adf2e2722fae4e33fc26bb9d03549f6f4b3b0fe57", - "blk.9.ffn_norm.weight": "c8b86cd5c43b332f72060b807091c33a258e5dac01358ff4733b916cd34c9c97", - "blk.9.ffn_up.weight": "d8cc3bcff18bd46124ba2aa7caacc71220b44eeef6fccb993b4c6cb53e8f2c3a", - "blk.10.attn_k.weight": "964bdf3b4e77b915a216f750ff7b0f2eb1dd6bfa071358aef21010b90111044d", - "blk.10.attn_norm.weight": "59ed411d91d14775764eb514acb0895a75a10cbbfbc1c15d453bc50f8046cb7f", - "blk.10.attn_output.weight": "4d35a2a44cfe4ac0a83fd3ab0dcf1f5a0bf54cdb3b7be9fc353ed32c8a3eb81c", - "blk.10.attn_q.weight": "defff5339450dd881ac352f5c459293f39e07b9619ebd10ed632d79a3f310278", - "blk.10.attn_v.weight": "b9803e8d6a54acea58f662d4c0a5c8ebdf986676de7dfe12d4b288937881ce93", - "blk.10.ffn_down.weight": "eba856be64e4be20b92fb4639a783454dd92427250759df92a337e39f1971c08", - "blk.10.ffn_gate.weight": "2d5c509b066584db4de3632b01234e86edcde35409c5ebce18957dc80fe465e3", - "blk.10.ffn_norm.weight": "ecb9a8679945ff0273856624ce435dd250ffe5a440ea0861a5c84f0e4c44d2c6", - "blk.10.ffn_up.weight": "e76ec7e993f399af02958778c643aa78368e3067846714165eb5aba9d5f547f5", - "blk.11.attn_k.weight": "29c6d1f34bd3ba2f0904e57b32a5bf8dcb2834d439159a33edf234ce0b775677", - "blk.11.attn_norm.weight": "b5817b275149cd2abe18a6a10e19854605fc58fd364666744362ceee8cfe49f4", - "blk.11.attn_output.weight": "1e05653220e237cbe0cc770033e183c9a0eed5680510997409b16186c6691950", - "blk.11.attn_q.weight": "03db725ae669151e4d536e50285b3b047ad097f52475df208ed3e790e31a44be", - "blk.11.attn_v.weight": "27cdf1d4e971326c451a4615a0b79a8c7fe9508f9b76c0d52fa01971fc7eb403", - "blk.11.ffn_down.weight": "176938cd7c2966094f614cace8ba568b10532e45a0d438f80eccd19b6c2a7f87", - "blk.11.ffn_gate.weight": "9782339915dd6fa70013628a01524ee1d01ad8beab04068da7ac6a5ee7603a60", - "blk.11.ffn_norm.weight": "8245f6391e3be97811c0ff27f0d8f484ecc82a468a837c893f059745bfcd95eb", - "blk.11.ffn_up.weight": "15616ddde096d0d25e906375c548b6de4bd5576d1f6b68eefdc29f14e183af42", - "blk.12.attn_k.weight": "66dd21604993edd1b1fe547bcaa06f5bb7e31c9204902d147a227e4badf7feec", - "blk.12.attn_norm.weight": "23a69f85dd8a0904b9839cc5d0afcda299b74e82ae2642106224a1c820f2b761", - "blk.12.attn_output.weight": "4a98d132e376beb274a39d4ea9b6a1b870ad5c66625439d7ff6f45c229c3ca04", - "blk.12.attn_q.weight": "1c6c309d63afcfde32fe37257e300a78e25d01117e33490801107c0e75d1ea66", - "blk.12.attn_v.weight": "723d9e4ebe4e2b1974afa01d8f512b52933698fa36717dd47b37b07760c50a10", - "blk.12.ffn_down.weight": "00e0fb09e1f1fbbf3803f1dee373eaae7a93756b6e13063ab77f9927bc6f996a", - "blk.12.ffn_gate.weight": "89159f7f97aefb1e100107e3ac2d694e1008ad873f79bb953d60c2c1bb22724d", - "blk.12.ffn_norm.weight": "5f70aebd0e43a39d6373d8658cc670c13aadd7818831d3d84f761d5f688442f0", - "blk.12.ffn_up.weight": "faec21b446f061eb4dca561a3180712724347b77a71eb312e7afe9be9e89fa04", - "blk.13.attn_k.weight": "3d440825d19eac3b1753b34d94fee2b3a3cb6636c10b2703ffcf688d3c1eded3", - "blk.13.attn_norm.weight": "47b575e57e410738ad13fd3c74bb49c06b3d31030910834ece509cd1a5c6d9be", - "blk.13.attn_output.weight": "05436d8e613f4475741c1798a7c371b53d61b229507fa04fe23c504ba1f0e12a", - "blk.13.attn_q.weight": "002b5024ce520da41256e3ded5cdc60e5ae07ad9b202cb19d76ab511efd02b1b", - "blk.13.attn_v.weight": "c1f2d6763587c50312cee0d7140fa2c7ee326f5b172bc99b2d8946e08329cabd", - "blk.13.ffn_down.weight": "b5c4e0d8a3ff96cd76a135e415b89f02d28c28f7f3c16a36af31ef0ab8773da5", - "blk.13.ffn_gate.weight": "ae06e9e3d2e1f64c7ad23a4009dc904c2eccd7241f9f91c4974ab2504f116be0", - "blk.13.ffn_norm.weight": "e44a22321bcbcb4a3c345b504e939e8071370f54a8cd702fabdb40b97e0d7683", - "blk.13.ffn_up.weight": "7e6f366d538e21ad431264b12c011892d0be9dfe4c4da9f730af677f920641ba", - "blk.14.attn_k.weight": "95492d6417952ec24b2cab87bceb750fc7e95ac6b1944fc328a3852d980164be", - "blk.14.attn_norm.weight": "6b7b09e1c51addcdbb160ea59edf032531421c520ec5645fe1ff9ca4180cef54", - "blk.14.attn_output.weight": "75887474e4d72c218e6ab0f69f1bf3ec3dc414d51b36fc59df00cdb23421bb6a", - "blk.14.attn_q.weight": "940e33f76e48c21215d19e8a21234c8246d4d084381a7d9806aecb24b071d5bd", - "blk.14.attn_v.weight": "c58601cf5a9833f80f7f9a5b2656e8eab5eb133211446ebd48f8be15fed4ebb9", - "blk.14.ffn_down.weight": "f9f886e7f9b2a54d717b08947a25a0a93e8c2a5b8bcd5a907c06817c8ee3ac11", - "blk.14.ffn_gate.weight": "727ed0ee68594a3f59d704ed3240b6929f083b9c36650fb848d182315737245c", - "blk.14.ffn_norm.weight": "bd2471008ff1b2bae9aa26bea019393fb2bbc5b9493b8cec3ebd2c280fca24ca", - "blk.14.ffn_up.weight": "b006446769f51e4f93b503c4727deae897bc1fc7f4fad49f85024b63c4548d38", - "blk.15.attn_k.weight": "23bb70f9035356624039547a603e46be7d1e4403616eafc2451cc09c5373d522", - "blk.15.attn_norm.weight": "718cb371ca052eeb3bfac6ac506abb887df125271821fd171797a7f2d8dd6313", - "blk.15.attn_output.weight": "c76a2695a204b43a8e5acfa5720590b5d449a9ad9e082cbe3e80fab5903ea16a", - "blk.15.attn_q.weight": "2b3e4037b9e91bdd26d6e8d904cf39f948192dcf09bb6445cb55ca058d4f4626", - "blk.15.attn_v.weight": "7c15e89b6acafc8619e86aa9d412f5893ab17843ff2cfaf40eea9637b24910c6", - "blk.15.ffn_down.weight": "e16fd4bdc6d1c1209c6b633454df4992870c8cefb2cb0e8c92a7e489e9fb5d19", - "blk.15.ffn_gate.weight": "95a46bea366c260337c537fde06b4cbeaeec52484a69c3390bb1d178eb0525c9", - "blk.15.ffn_norm.weight": "37730293f704da265dc6d1896b3be00c39c0a41dab07f573af39dc30a481d623", - "blk.15.ffn_up.weight": "ba74a199da2d0875d7410824238c4ffafbda3993568812284a72b8800df91f15", - "blk.16.attn_k.weight": "f58f79a2a91c9a763adefce0c53a71eb5ce6bd8442f4af554b04b58083bff27e", - "blk.16.attn_norm.weight": "0c16e41b95e81978e0e0e3b338e2afe2d297426578cacee94de15df74e94eaad", - "blk.16.attn_output.weight": "ead22fc337514e4add49aee19720008558e52090466866e849671953a1fccba4", - "blk.16.attn_q.weight": "ef59c4e8fe8918c1add43d7e9c6fb3ef799dd3e1bdd731ec7b6a4a6f97c86048", - "blk.16.attn_v.weight": "902e6b84c2b64241470b13e6f412f859f66b4b223bcfb9c15d5cb1106b07ef3b", - "blk.16.ffn_down.weight": "2ad6e9eb4d8372c32a554395d460d17cfb02d6dbcb757cc962b6bfa36db4f5ee", - "blk.16.ffn_gate.weight": "825b2d50fcce3dbe6a5d8d8a50a95466f83ca4a10343efe67894c20b4628fb15", - "blk.16.ffn_norm.weight": "3bf6ac90befb0e17e077c8ea9454a8485a30f89f2d761ec7751b60c90aed1af9", - "blk.16.ffn_up.weight": "9fbdd08739b32411f5ab0252174d386bab19eb0b17884862f760429b7d41d78c", - "blk.17.attn_k.weight": "4033398718bf3674830ed1b73071ed8482b6dd4ef27f31a6c5fbb998321b6c07", - "blk.17.attn_norm.weight": "714f2e8ac9592966a0f1c02ee979eee8f84586405b992e8ee9543e840199ffa1", - "blk.17.attn_output.weight": "b6bbb618597d767b8f535117be68f92911e4a71d4eb4d8b5d943444151445ece", - "blk.17.attn_q.weight": "b84a0dc00ceb515faa2628125dcec502eed923077b21cfe900a4ff16c2e5f9ed", - "blk.17.attn_v.weight": "4387c7d6a17da9cc7a6bca8f4a75618b20407d570792056283a8e93b6ec65f18", - "blk.17.ffn_down.weight": "47db95c6f1e12b399c3eaf9ddba261782dd71173dd163b52af96541cf87b5196", - "blk.17.ffn_gate.weight": "59abaded0aedfd12f01df81f7a811e84db6a227f51b60abe9a247ca726e87392", - "blk.17.ffn_norm.weight": "b7e86445be5c7b722e01ddb98d5c7527ca86cb827ce0354f2c269e0f2558751e", - "blk.17.ffn_up.weight": "8e31c293bac649d2f60da4b3fc4a3acdce1111ec6058d8805eeeb242443011de", - "blk.18.attn_k.weight": "5ce762ab7b032511c131df81093b587871718c7097f79d8e07d707571f18a47b", - "blk.18.attn_norm.weight": "1f52cdc7af1f4dc1f0ef6ad1ad02e18cda32133654e57cfa9c72ada9c0b1d995", - "blk.18.attn_output.weight": "6486957f30bf8a88516e25772c6650f98b13923f490a2865a8752e36439d1cfa", - "blk.18.attn_q.weight": "93621c8abf69d2ca29c5207180eb628fb2b544d89de6c4a7fb0699be95534899", - "blk.18.attn_v.weight": "11604083b5a74828ac1d226af015ad5dc0215a1fdca44fa7131c2163c02d8156", - "blk.18.ffn_down.weight": "8f9997feb94385f106915df810239c9753b31efda2bf14bdf18a9fbbeec8233d", - "blk.18.ffn_gate.weight": "427c213b3a4e94af703429daf2f65766f70424d8230c123e7e712a18bceb5ecb", - "blk.18.ffn_norm.weight": "c45d305c4ea6a54013ba112f12dafaade064a32cf01317373464a3618d8ba44a", - "blk.18.ffn_up.weight": "a2811f2e73ac9eb9cce91a21a454e84e230a155244e2cd73f2c12aad3c9b8cfd", - "blk.19.attn_k.weight": "b2daed159925eac58c291e2f1e2000beed21002b03c9e1bc7e7a52e22240666c", - "blk.19.attn_norm.weight": "6307306ede2ab5bffa1bcac3f8b139354678c0376b1d9f5530c1fcb4268cfeb4", - "blk.19.attn_output.weight": "ebb98218b2a9c84d3fb6baeb02c5df264b7ab80d994d1098ba1cd47aa398effe", - "blk.19.attn_q.weight": "4f10df2ad09177e7528e9456039b670d07db22940a49417101b725d239c16724", - "blk.19.attn_v.weight": "30f1efc5114badaeaafa91fa466dc7fa14b1616db433c6f563ab851f7333a5dd", - "blk.19.ffn_down.weight": "be5ec7fe6b48855cd0015b0e430d1b70c620de87a7ff188c7c1afef546d7b6bd", - "blk.19.ffn_gate.weight": "10dffea4213881f8a9b583ee0fd370e033756d32255ed15053f794375b9400e9", - "blk.19.ffn_norm.weight": "e75cd24ade45dca78fdb0cbcaaa2d4a17d83a5a73dcc94ce0ec2d68fbdb2a881", - "blk.19.ffn_up.weight": "63e81bdb951410ffa81bcfba1b94a679ec9ebae59cd1623ce2651ed5d4c78bfd", - "blk.20.attn_k.weight": "c2fc5ad39e9bdd45e73c6e54aecc474388d944c4be1ee1921b7fcd035bad02e0", - "blk.20.attn_norm.weight": "aaa9169171937bdce20c1f057e94e9252f221cabacf1ced12e11b9586f23d308", - "blk.20.attn_output.weight": "a9f4fb496e4bc053e3f6cf2e72e22d4cd2b545ef6c32f7e782c2ef6ebcc21d4b", - "blk.20.attn_q.weight": "5a07ac619ed251494170b213921ef3fcc4c2712839da262516d9d5b8ea1ff185", - "blk.20.attn_v.weight": "d6689473105d241eacb17f09f06000ee237336916cf5ec4f48271c5b41bcb8e7", - "blk.20.ffn_down.weight": "74be38db51df736f26ede7c6b52ea787e385f181cb66231e2cced4556a25c9b8", - "blk.20.ffn_gate.weight": "ea91e06dc3d051c0ba0243b5a8bb40edbf254eadfb54fda7247e05cfdd88cbe2", - "blk.20.ffn_norm.weight": "5fbd357b3d6f44a7a91e8a4fc246b24303891b7957e0f3c32818ae5dc16ddd8d", - "blk.20.ffn_up.weight": "fe3290333e056af4ed12942ac72aeba97a6b562e2db05e79cd35dd07eab5b101", - "blk.21.attn_k.weight": "201ec6ee95f06ea5eb80fe86fd07bd016d3ae9ab6abd25d631834414e14a010e", - "blk.21.attn_norm.weight": "ea8154f93e06485828475a00b98cc397ac84768dd70e06ecc0c075b5712d7276", - "blk.21.attn_output.weight": "9f8af74d531478fd304723fd8e4e01578db598441b80dc7c960cb801dbbc501e", - "blk.21.attn_q.weight": "277de9953a8d3cff894ffd06c15ad0ee1407e319df0c1a693d4f45fa9c74ac7f", - "blk.21.attn_v.weight": "6bfdc16cfb898909b7788ddd39dd04b928f31d6732772195d53c558004638dca", - "blk.21.ffn_down.weight": "173877146cb94801157796ee9e5eecf3f46acb3b5e797f90b83a3fc22395eb30", - "blk.21.ffn_gate.weight": "53146713e2ca1be80496024077a028f6b6d749b02e71003c349e113b436f48f4", - "blk.21.ffn_norm.weight": "b28b97e18ab20a5c553ba422f7d7f6014f5902f1d62a69abd20d9fe19a5f9462", - "blk.21.ffn_up.weight": "5c39d0ac4d602b8ec8909dade93b2efcd6b6d9d84a19b252d76bb66dcfaab87c", - "blk.22.attn_k.weight": "01f26272c82917a87a3ccf922fa1d521a952b05de878241b7efe3525b617ac87", - "blk.22.attn_norm.weight": "5ffc96249d8873b506e9eb7158bdfd07fa1429e53c1951430ca7505d25f11c76", - "blk.22.attn_output.weight": "9c2201569358f720244b9c9497e4da02585a167b1414c8a506b85ad75ba990d0", - "blk.22.attn_q.weight": "906036eb4ddf027f6d920f9356a6a2a5e529b96f4e1231a0496d46b4434a5842", - "blk.22.attn_v.weight": "30ede8b0d166003a4b8a81fc99437f557719fc36e5c4dd510c9f161f36a47e73", - "blk.22.ffn_down.weight": "d04c164beabab30e1837b843e18852260efccfbb9d96a34ddd816e6fb3ba23c5", - "blk.22.ffn_gate.weight": "19c889db6b19179f0a62d5981a1506592c65de83760d67afbe00d202202750a8", - "blk.22.ffn_norm.weight": "4885eff2d851b32dbd306bd632c725857e6d164f0fa8b3d5857e572e6ef98ee9", - "blk.22.ffn_up.weight": "365594d8db8e95cf87cc33ac23947942dc326110175cc8ec5a07b5c7059089a7", - "blk.23.attn_k.weight": "badfea1569da0fc6ab817c5727ca3a69b07d9cfd622fb8be5e66678d5b3f7ae2", - "blk.23.attn_norm.weight": "8968f78a379ac3ca5458b4ed4251e8d9112aca6d6dd1ef6440b4bb0b380375a4", - "blk.23.attn_output.weight": "93e43393c03956287b1fe31e9735ff1cfe84f4ae56b83dbaebe96275e4e11831", - "blk.23.attn_q.weight": "aaff73c725a8700ae66bf26ac8869dfe96738eff23a8ff340de2ab53400a5795", - "blk.23.attn_v.weight": "3a86a8dcf14a746ed1411f5a7e634064bc4dfd6511c24cfeccfb2c9ebb6b4101", - "blk.23.ffn_down.weight": "d4da6f37bd7ef69bb203f7b0dd59f50bce37432c70627e6cf274ab81548af5cf", - "blk.23.ffn_gate.weight": "5b6072936c4a693923bb4e3d1473fd45545cb02fc07799aca458ef0449a04061", - "blk.23.ffn_norm.weight": "cd76e37025f84773180298ddb15e0d4ba9cfc7d832e19c791049daa47c6d9c10", - "blk.23.ffn_up.weight": "cde43b99b83124a13b2e4753d12674b3a61dfb34c04703007ced3e8e2aee1801", - "blk.24.attn_k.weight": "457379edc4cce4cbbe107385079019bc922264fdfc7bd1d1ae84343a81460c66", - "blk.24.attn_norm.weight": "0ce0dfab2edeede5da419fa7833db78e36222cf25c358d08f3ec664310f031fb", - "blk.24.attn_output.weight": "0cf91c2fd40c204d2fd4b9c85b69281e5ad4ea8442972fcd44b5fc8e835ffdf8", - "blk.24.attn_q.weight": "87ede30c09eafec6a4e6285674c1bc4637140b168b2da4ed34f36fdb6e176cc9", - "blk.24.attn_v.weight": "4c0b078b2798ca35d6d2c2258fe499820d2bc88700654ba4016e4b028f563590", - "blk.24.ffn_down.weight": "cdb8540c32b1ab988f984484928d39f6841f2131c1cebe90ad9456737fccbcaf", - "blk.24.ffn_gate.weight": "da2e0e913648b5526bd2bbb344038dd067639343aed3b413662b064b0db7556e", - "blk.24.ffn_norm.weight": "8940bd781c610d75eb2be63cfc8d869a3af05e53c963dc7fd4c6f653df5a80ab", - "blk.24.ffn_up.weight": "90cbac2a58801abe11ed6c24560aa4acb949f79429f2aa8ff129ac05868bb87d", - "blk.25.attn_k.weight": "90607131e36998e990ce718ad05cbecd1bcaed010931401ce6baa3b0d93ebce6", - "blk.25.attn_norm.weight": "fbf679c85656c04a6cf8fedd5412c1ace22960e6c2d47f2d43997827811fbb97", - "blk.25.attn_output.weight": "08412724ee7a2086514406e6f68fb9f622e10bac25b0c373b294709f4b09bd2b", - "blk.25.attn_q.weight": "9c1238e98a2747654a0d4371d3e7ea8b979867f609dc42482544f25591e85c7f", - "blk.25.attn_v.weight": "a57796a535c6cb09581cbafd6a91dc14adc8cca2a2465a7ffd0aec546cd84074", - "blk.25.ffn_down.weight": "f7e34e8a6391b480da08b52640613ccadce268373934b409759743a1735b74d6", - "blk.25.ffn_gate.weight": "b8d0b2f4612678b5ce42bd4a683f8024514b75fb5ebf6b22c600811e95582ee4", - "blk.25.ffn_norm.weight": "cde1fdba2369d315f3c6940a997c471ec891924e642505db580d732763bd7b75", - "blk.25.ffn_up.weight": "72e700c32ac8b9c47559c2222e45888a480b527ea512075423c5dc01678e2bb3", - "blk.26.attn_k.weight": "6ac83b3414ae75bf3a9055c32e49d2c40fe611ab21f8444f03d2f465d18122c9", - "blk.26.attn_norm.weight": "55f9d6dc9d75973dc75136ecb9d991b4398097ac133070873fb96ec76a6f60bc", - "blk.26.attn_output.weight": "ebc4fcbd15b33263e50ed2ad45740867cce15bc90e1216623babcb1820734509", - "blk.26.attn_q.weight": "080f057521073e412936fe3fee64fd574c8128fa4a148b879d3e598fe4954581", - "blk.26.attn_v.weight": "0fa2830d6746487ac91b243716e4302361f891e4e008eddd14abec47c7809d5e", - "blk.26.ffn_down.weight": "cb2ab8af1653adc57111ada49d2825c6995e338c8208455b92de10e580f60f31", - "blk.26.ffn_gate.weight": "231ce30966086bce2dc0e0afd34a22a1958cfda7a57c41b3b8e9444c5dfde8a6", - "blk.26.ffn_norm.weight": "35d959d25d17b00617590f5d5831bf705c385c51e46297a14375a700effca6af", - "blk.26.ffn_up.weight": "367680c8d332538b467d1ef87cfeb36cc5c6af564c5023c5fb50e728e3438287", - "blk.27.attn_k.weight": "0bfcb351c6d17aeac5b55a915074fbdf00f11c4bda98babb196ac8804805746b", - "blk.27.attn_norm.weight": "5d598a88c2e75ba59dd7ba4fee940bdec92d72038f1286536d2dfb71d008a09c", - "blk.27.attn_output.weight": "23a9da7347336479f6a10ded14cb3f46e06b5bd56dc4b0fbc526c688552ec840", - "blk.27.attn_q.weight": "b83319dba9055f069208e9c9d66da08bc6874f23e575288fcd81697d1777aa54", - "blk.27.attn_v.weight": "36ed34ccb2f36fdf16b2c2dd225a98ea6b7b0e376e7791191136ccd7bd7a4add", - "blk.27.ffn_down.weight": "5488e1d3a58c71b5e9ddda430540b4776b268cfe1457cbc1c2622dedd9e4526e", - "blk.27.ffn_gate.weight": "4ff48011ee0bac39af704849d9132a2410392c87a509c684f2062f6b76b498fb", - "blk.27.ffn_norm.weight": "32afe99675983da3de2961d1b5ca41c98970a356823597fe29e91f6e86abf0e8", - "blk.27.ffn_up.weight": "1eae3088a75629571fdbf6a20f141bc2bb2ed3f5ba2b9fd1d949f80695e442a1", - "blk.28.attn_k.weight": "c4e80af714962d6f9040d2c09f316f4a1cbc3a2e994e19902d7c653cf3c73dba", - "blk.28.attn_norm.weight": "c1ecf85dedc1c83d5d402bb7c94fb8b9c11f1a3e5f64e7680f80912d4a560794", - "blk.28.attn_output.weight": "72ba47c061b21f5ebc5213a455eaf6fc49c8f8e04ff9ce37e6ed4921b629161d", - "blk.28.attn_q.weight": "c4abc47234307f44b8ca789aa6668e298158fa4b459b2c1e84bd581806591cc1", - "blk.28.attn_v.weight": "aeba950799d4950e491ad0fcbe30334e39b8975177990a2cb339031c45ac153c", - "blk.28.ffn_down.weight": "4e84ce382a37b994fb8608df451a60040559e3f4f3241c3b3cb8989a3ed50d83", - "blk.28.ffn_gate.weight": "04df157acdc8e8534ad60acc2d2a4dd3a7a6610f6382535ec728994fa6f83f83", - "blk.28.ffn_norm.weight": "4d0386dae2bd1c1a9d0f9730718333e3a486c3bc6a5c5d482193c75d39832c80", - "blk.28.ffn_up.weight": "fec60bb0a3daf182a14bd8311fe6dd1e3fd020c5fc273e2549cdb1a2d6b79b05", - "blk.29.attn_k.weight": "b0532a263aa5a4e2a7a80adc83fc5dec974493bd18da7f953e7ebfc3f3a19aae", - "blk.29.attn_norm.weight": "593fc3b4000c35b7a59dace09ca1756c08be0105b2edd354a0e1c16c82898859", - "blk.29.attn_output.weight": "315b896f9f0cbacd0ca8937384c3a3a227efa908cb8c3a9125ec00c480e32b9b", - "blk.29.attn_q.weight": "d482d45386d4ad3394f08e9dff233ee3a70d0427d65c0b8fa05905da7e25ca53", - "blk.29.attn_v.weight": "cd3b5a6e2852da796902930a6a84bc87fc6a7c7bf51f8fc23758d12a39013b36", - "blk.29.ffn_down.weight": "5b3dba6f9753bd1b1ebcba65ef5373dd62c38e755c44b7231b95d93d45761f89", - "blk.29.ffn_gate.weight": "8610d9d2db15c256243ffcca3ffd31786d0ada0af0e7c7aa3fd20524370ab036", - "blk.29.ffn_norm.weight": "1a2ef2d38b7ac3e51190b9ccb8b6552ba83ab290e523356a7f851ddb35dedca2", - "blk.29.ffn_up.weight": "a5fdd15811bde16dc27677cf1a4c97daab4c28cb12a9530f1a0e573134fdb69c", - "blk.30.attn_k.weight": "1efeb0b5f4b45a85cdf47300f892ac77ac1f38000ec3653565d1303d1fb8c743", - "blk.30.attn_norm.weight": "c73934c182c7fe80838ec1d0b92f50a583f75f7a3d78d822f009b58ad2c80e65", - "blk.30.attn_output.weight": "3a0fd89de2d274614750345d827a9c886a4f97b343a13cdf680390505df596a3", - "blk.30.attn_q.weight": "711e113362bdb067db843c66236704eb1cd3fc5f40e3767143e96d510686ef4e", - "blk.30.attn_v.weight": "82b12a9a74fd3d91b73cc2e841e2b3f0a5197ccd2998afa17020995f880d2267", - "blk.30.ffn_down.weight": "af9f4b1287c0d824ae22d6e335d19e04a70135b835be7caa2435f1d85e931993", - "blk.30.ffn_gate.weight": "e2ab3e6f15f5c50fca66c084cb6a57a2b6b82406d65150e82ea0437b93dd9a46", - "blk.30.ffn_norm.weight": "c1b9c325c83f00e177386a4d7e769945f2995e60950c4a576c0a2c4ab9703d04", - "blk.30.ffn_up.weight": "9b94a21efd419715d82071b490d3b635cf1e8da080620dcc39e5bde976d7e9a6", - "blk.31.attn_k.weight": "0db0d82e3ddcc2c06209f5f013e1d72a84a996c40bf00186be485b909cc268e8", - "blk.31.attn_norm.weight": "2b8b7239471f57140c5cdfe06bd224a4f6326282f99736e44fba4c7b120ac101", - "blk.31.attn_output.weight": "a310b048840cc3ff2be4b84796340e8e2cdf05ec89d14bd3655c109b2bfa9fcd", - "blk.31.attn_q.weight": "f45e0cd95645175ea82813455356d171838539bc3f7676d877c698f2af0a0eda", - "blk.31.attn_v.weight": "8bde008e809112aa7e7c23e9c3099087bcc557313b01306c87efa0a4a30805ba", - "blk.31.ffn_down.weight": "8266fec7e203fbfad7033120861e44984581ff8b6851d01dfb7b81c5d8fa90ec", - "blk.31.ffn_gate.weight": "b73bc0aa5baf006d9ef6403104891b8133671b0992398fe038380b67e0d7e2cf", - "blk.31.ffn_norm.weight": "9c62cc27a7b6017c1df8ad49bff249a8245e8895c6754f402cd44623fda83268", - "blk.31.ffn_up.weight": "5b970a4694ea3171a0167f6e1636d9f00268bc1c9640430ffc35218494884adb", - "output.weight": "74fa0ef08c57a30e633e7117b1e9c805f833e2e5e21434bc79ddf9c92c6d7330", - "output_norm.weight": "59b8a59fd3fbf39353506116e43e5e76edd0cbf2a2873d869da4cf27a04997c3" -} diff --git a/ollama/convert/testdata/Mixtral-8x7B-Instruct-v0.1.json b/ollama/convert/testdata/Mixtral-8x7B-Instruct-v0.1.json deleted file mode 100755 index a159653..0000000 --- a/ollama/convert/testdata/Mixtral-8x7B-Instruct-v0.1.json +++ /dev/null @@ -1,348 +0,0 @@ -{ - "general.architecture": "llama", - "general.file_type": "1", - "general.quantization_version": "2", - "llama.block_count": "32", - "llama.context_length": "32768", - "llama.embedding_length": "4096", - "llama.feed_forward_length": "14336", - "llama.rope.dimension_count": "128", - "llama.rope.freq_base": "1e+06", - "llama.attention.head_count": "32", - "llama.attention.head_count_kv": "8", - "llama.attention.layer_norm_rms_epsilon": "1e-05", - "llama.expert_count": "8", - "llama.expert_used_count": "2", - "tokenizer.ggml.model": "llama", - "tokenizer.ggml.add_bos_token": "true", - "tokenizer.ggml.add_eos_token": "false", - "tokenizer.ggml.bos_token_id": "1", - "tokenizer.ggml.eos_token_id": "2", - "tokenizer.ggml.unknown_token_id": "0", - "tokenizer.ggml.scores": "e3d3eea80bb41a1213f2d0aa3e8a38581d1f19323be77dbd779c9c7e3b72e676", - "tokenizer.ggml.token_type": "6040635e6bd38d98af06698feb75c1802bad35180ee6ae0a503e38c0f60fd71e", - "tokenizer.ggml.tokens": "604ac4bfbd019e430d7b6cdf18c6c0cd5b967900601f0307f714ec7773aa5ca6", - "token_embd.weight": "1d1d1d39a867d5a4bfb32792a47247d2638c10c95a6259391d02843583505cc4", - "blk.0.ffn_gate_exps.weight": "2e5cd43ac3f26c44f071926ff6c3f239ecc52a34bc9a5b5906d3d4c1bf2fbbfa", - "blk.0.ffn_down_exps.weight": "a4dfc7e7c96e7402eb70279601675b956bb7331da8101e63fe5c0a611b6972e5", - "blk.0.ffn_up_exps.weight": "2d5d87b378b2319c344ed2c642598b6f7cb6beeb582a8ea51abc9ae690d473c3", - "blk.0.ffn_gate_inp.weight": "a46aaf5aba7401ce6e41f158242b4879d34901661f3ede85496cbd0ce79d6314", - "blk.0.attn_norm.weight": "3fe37d913bdd2b65076bcdd6efe64a37b0b03cacbb1b80b9f7089068aa35f38c", - "blk.0.ffn_norm.weight": "5e14308a3c894734eb204c8f558bdc817e94bbd5b4e9cb4094e91ba388c8f7f2", - "blk.0.attn_k.weight": "73d943dcac0911e87bd771f4aa1c901e1bfe1aed293af06e1a67812159859f67", - "blk.0.attn_output.weight": "4c5f754c855e262e8d4c94c6fbbb57af06399dc0e170d7d99a1a17fc9aab9227", - "blk.0.attn_q.weight": "d6fd7403c873d49c05f6f03208f30d99ad34cb3b71c9990c47334d502a8e4c7b", - "blk.0.attn_v.weight": "cf17cf64b2d683bd9de6cebaf60e5c264df6fdc38fe719dde9d54c80334f6366", - "blk.1.ffn_gate_inp.weight": "0d524de81cd915816b4e714bf595ad6946a9130b3de731cd89428b2781230809", - "blk.1.attn_k.weight": "2ea47f412992b374c70674730fe84700e0c8cce177086ce9b6635e42408964bd", - "blk.1.attn_output.weight": "b4b2520794d54113e86c8ff678eacfc62e35be4395a594a6c8c22b4383ebcc0c", - "blk.1.attn_q.weight": "5db930c98c4f91f6eab57eb974c72210b158e366d23d6d2890b2759c053bee33", - "blk.1.attn_v.weight": "079bdde09668394bf7af9f8bc175017b4f48f0ab64e6dd855a4d7561d1693c0f", - "blk.1.ffn_gate_exps.weight": "146a62de19f9ab093deb101f9640534ffc3dc40d69f508be12fc0475d01b0c7a", - "blk.1.ffn_down_exps.weight": "949da94a3c0f375160672a979e85f7def284264b10d48d038238aad5f5ece793", - "blk.1.ffn_up_exps.weight": "7016a3f467d9e3f2f4b4019579ed86b757469cd367f2b225483305376b4bb3c1", - "blk.1.attn_norm.weight": "1614d1e6ed537737275eb888666c7bac533f4eefbe73dec92b591045ca9e1afd", - "blk.1.ffn_norm.weight": "405a455fa7d1ec36894652ceb554bbcb09a07fd6405f42741e66dc4a4665c19c", - "blk.2.ffn_gate_exps.weight": "90d5003fc7421f44220c0842d43128955e91488f6f785fe570b62d81b719e964", - "blk.2.ffn_down_exps.weight": "ecdc2b5a8b504ef0a7833acff47d69b0c1fa9c22126de1bb120ff5e48c3d6e2c", - "blk.2.ffn_up_exps.weight": "2cbd9485a32460d315eb50a2f3b00863fd77245bfe885b7565efac1cdb1f191e", - "blk.2.ffn_gate_inp.weight": "0d0a17a1a2c7a61f2cca49ecbb479154dc93a870873257bc4f225e7607f2e2c2", - "blk.2.attn_norm.weight": "b2e4c5a977f87a6f880896bd73596234c9b83622fa0d7add5892501e3155913c", - "blk.2.ffn_norm.weight": "0ab875b4280afa922376cfc7b9aa3f7071c9432ea1254091ce7de3749df0e8e6", - "blk.2.attn_k.weight": "bb884af51fb51550acfef54ccf1b58ce8284e587806e6a2f88c8265e1ad05a5e", - "blk.2.attn_output.weight": "0f03099ba1ef342ea61af9cd71d028123bbd8b1dd7d7fd9b509aef77815427d9", - "blk.2.attn_q.weight": "8fad0d29eb4c9d24e564774ee3316b9eb7a4c4985e4567111d2c836c830f6cf3", - "blk.2.attn_v.weight": "fe04c847ff677632401a94e7b6b6fdca60391ab21cb23bd791533115de6303a1", - "blk.3.ffn_gate_inp.weight": "29e3aaa724590c070e614af8288939603d2641b0ef11e8c0f476bebb2776673c", - "blk.3.attn_k.weight": "231cc5631def10f7f292d8862d6125ff555164cd70480ac76362149fad204497", - "blk.3.attn_output.weight": "86467a605c62852e05fda1a7ef43150df2cf715fe59785dbcba09f1c27cfa086", - "blk.3.attn_q.weight": "901822402453922225c2d6ac79616691d48217635d5ff7338daa971d5ddee210", - "blk.3.attn_v.weight": "27030784f44375720df2f090933645a31a022d3fb3b14573e5ca0b78f44070c1", - "blk.3.ffn_gate_exps.weight": "231ba59cc0b988d125d77bf627aa3f04636684870af88f081f3944b48a160d86", - "blk.3.ffn_down_exps.weight": "530c3ab44ae4d66e8afa4d10c153ba5dfcdfb7321989a988e62e9d12e7234625", - "blk.3.ffn_up_exps.weight": "b85c2d4d9d11332e702b3c0a6610d4f525f9a93e5d12f5c7c55c592c40755e75", - "blk.3.attn_norm.weight": "05dbb6d88cfa6b199f9d705ccbda97c0ef13f9ec875c595398a1a42d009a4555", - "blk.3.ffn_norm.weight": "6880b1c27d46969ce36fac049c05dc8b89e4bb47dc89df357e32df7e18fc512e", - "blk.4.ffn_gate_exps.weight": "a883b4f225b760c5a2f6605dc5e2167ab85bb398c70bf64ceb539fcbd6128dcd", - "blk.4.ffn_down_exps.weight": "d291bb656aae77947d4b525e2819bf4112afece53ff31de9dab999af1f65f9c4", - "blk.4.ffn_up_exps.weight": "38592afb8ba3dcfb26970f906174f7d3fa62da44fa4be4fc6912a19030ea9164", - "blk.4.ffn_gate_inp.weight": "1596cb74e8fd6c3080b937b06468bb397b0dbb661e6d180a6bcbdc43e8bfd0c6", - "blk.4.attn_norm.weight": "f90c83c5ff4366281d283384efc941620542b9cfdea160d678dc54a75e33f758", - "blk.4.ffn_norm.weight": "d28d8c49d1746b7cc085562d1074905fd14023844de823dc4fb22202bb280790", - "blk.4.attn_k.weight": "792bbf412cc357140fdaba543e547a9b2f7582919e307bbd9a80c7d6d8f5f1f9", - "blk.4.attn_output.weight": "d98e4a062d2631d9c315f1990d5f6ca9a88e7e0e46387f611ccb0353f876aa12", - "blk.4.attn_q.weight": "1a11a55a91d9f748a72176ff6b1c174844df406e00d1b66b9aa64dc6ee4bcd1d", - "blk.4.attn_v.weight": "04cb3c02b12a6313c7ac7044513441083d534fb4c5a3f63bbaa58f7edbd2fadb", - "blk.5.ffn_gate_inp.weight": "cbd5cdf015d33a2da6703eb74c22fcb97581fb9175435173b6dc4f9e8364320d", - "blk.5.attn_k.weight": "4fdf3405e4d657403f5647b51233521310ee984b4b81bbcd901cb3e6ab76b7ff", - "blk.5.attn_output.weight": "4a25662c46979a29600ed77e1907cf81fb16ef30e724c155444e54ccb76af481", - "blk.5.attn_q.weight": "e2acb30e30b97300039bb20ad0878f05159d5657fa811748a51d5b6fb35d631e", - "blk.5.attn_v.weight": "306504b6a26aa123c63dbbed3f4ced0ed2ee8fb6a30bf0093539b817539f5ece", - "blk.5.ffn_gate_exps.weight": "7e34df9b9944dbeea5e8565786d3aa6937314a4b87acd4d0874687877c5a39fd", - "blk.5.ffn_down_exps.weight": "c4b7a57a42b5ac0a8ae27dcd5cb2646d7a7cc7123126d44a56ab128e85f60b13", - "blk.5.ffn_up_exps.weight": "09d47593b6dd6c664a9155bff02fc2eb7ac4a70219a88162d05c802a01d3c6ba", - "blk.5.attn_norm.weight": "58804a036d6ac4c1fe357b8b6a97a5c37cae1c2f06ee0086c041d449c1c6ef6a", - "blk.5.ffn_norm.weight": "d872dee6789f0826211aa46ca9d0869e3e96bcace9e77d6559a7b6f3e524f3ca", - "blk.6.ffn_gate_inp.weight": "fb1eae732e974d6c1d020a5b4ef98c5f33016f984701bcea656f999a99daad66", - "blk.6.attn_k.weight": "55e9c59c5051ab5519b3a7962e1b5fa96a3c0251cb6200dc2f177885ad2de470", - "blk.6.attn_output.weight": "f3c834a8d0027370350e2b6294d95434d31432e57be6313b013c15a56303d61c", - "blk.6.attn_q.weight": "efaefe5f11c2140dc7cb532b0832c2a0b363a165cbda21f00fadae77efca377b", - "blk.6.attn_v.weight": "900bd734d75616d846a90a121c97e081c956a3d1ab012f66dd0bc62c43e1ec3c", - "blk.6.ffn_gate_exps.weight": "312a99661b1468fcaed2474621116f1681432755e973f3ee79d01912974fd424", - "blk.6.ffn_down_exps.weight": "ac9cd7db67a2ef0d2b5def86873673d05e48d49d147dd944469dbb8e2d4c46f6", - "blk.6.ffn_up_exps.weight": "57613e7e09579400a1a09fee4445acfbfe83f2f327fdf317877787d96ada6b84", - "blk.6.attn_norm.weight": "0e8801e09885c633bc01a9a5b85d4e878d30158a4eb41a937dc5b760ebd044cb", - "blk.6.ffn_norm.weight": "b8c58062ac93072f878446b0e7f958c737aa47fb769fc3a8f593133d12db2dd1", - "blk.7.ffn_gate_exps.weight": "1ef611732ff13edfa8d30981ed9dac00c15ceba9fc012ed0b199e9280a849948", - "blk.7.ffn_down_exps.weight": "856c6811945c7b0fa461ca17811cfa43436b4cdf5326bad23cbc30883486d7cc", - "blk.7.ffn_up_exps.weight": "6725e3e33994302ee13fa5ec163631ce2dcaa08aadde8fc166c2265d4561c5c5", - "blk.7.ffn_gate_inp.weight": "36b49d7f80c1003dc392b2c1b9960cd49889dd69e77b26b9e4b13d01f3d0a32a", - "blk.7.attn_norm.weight": "7a0ec49acc5e20ee71c6f80ca02f4f1e564c485e0ae0621309e7c2eb0c616cf0", - "blk.7.ffn_norm.weight": "eeae035c39ab6e64bc06a4baa1bf6e50d4c8b8797cb0ad8abd48be86974802c0", - "blk.7.attn_k.weight": "e8f78c1def01a7a38d2d9bf7becb17755e28fefe4927856f7890fbee52840187", - "blk.7.attn_output.weight": "5367f05ac3bb49ef8745ba5902e1bdd4442415a3ebff2c7e1a3918d7be6fe948", - "blk.7.attn_q.weight": "37c95fc5acc55a4f6e5f02cab9be60e4fe54c08b65f98f4455741b4aa542ff4e", - "blk.7.attn_v.weight": "c89f1343486ba55814233511e94090f7365662a8a4214aa4c278cdadc79196c2", - "blk.8.ffn_gate_inp.weight": "4e239afe8c7afb8de3a005757c887cf14b1622ca2d224227591cb0e5301f4c17", - "blk.8.attn_k.weight": "2ad0229f30fdcc1e85ce64e00d8f75902238294844a81d5af43e14ba75c02983", - "blk.8.attn_output.weight": "2e44a4722acb3b521b81d0b910f8ca2f6c286d874a92ddd02150566454061699", - "blk.8.attn_q.weight": "1cd2b09cb2f43e08de776b5f7eac197a5a6d4ffdfd52b21baa36319450147bd0", - "blk.8.attn_v.weight": "5a22c57ebfd33ac500cbcfd321d5b5b1783f8728801db6f3f8bed51c7183e4db", - "blk.8.ffn_gate_exps.weight": "91063fe56cb4f3ff3b41052bb5046fcf8ef61516a603ee90aab893a9d68c15a7", - "blk.8.ffn_down_exps.weight": "d4c3abc8f1d1b462f67f70bd8f404b3fcf45dceeaa8527fa120527254c383c90", - "blk.8.ffn_up_exps.weight": "76a1a1f08ec577716a2e7027b45293e9205751126424f1bebe1de89c78f087d5", - "blk.8.attn_norm.weight": "f980d774da39eb76c52358afac3e38cb4c81cb323deaabbe5c41822e3f17a98e", - "blk.8.ffn_norm.weight": "1c937658cf90f1a85db9a5f26e077730fdd4b694607dbeeb825c5fb2bc407e0b", - "blk.9.ffn_gate_exps.weight": "a2532471ecb7896d5c78e5a34e10cfaf4125265e1595166c8d0d0dfbe2a3187f", - "blk.9.ffn_down_exps.weight": "b47921a28412d48fee450b8b9d97cee42344a2e69f06d407fd9523d7adf13333", - "blk.9.ffn_up_exps.weight": "7c461bd1b2a73b439cff6a10d94afa01e8b06f7e6f09d9a6f28e3876aef48bce", - "blk.9.ffn_gate_inp.weight": "1648dfb08b5c06d7953a5a97ecb764995fae9487fb729a1c867023b2538149d0", - "blk.9.attn_norm.weight": "8635db0f299882a63b7cfcd1d4259c9e53fab22c31d3d054de36b1001380b31b", - "blk.9.ffn_norm.weight": "f9309aa323062d174c463613afef9b0a33501b510bfaa58a8e0e866d12ffef3c", - "blk.9.attn_k.weight": "dfe62030441e947a588512d18d9c6e4ed72c2f71c227d622c095e4263b23dadf", - "blk.9.attn_output.weight": "1977beb75c6349c50ba7dd3865d7c0a9c5c5ddc854413147b0eec98ac4fda351", - "blk.9.attn_q.weight": "eb132596719605cd6bd1782487f121994629e115190edd69240b12af66e734f5", - "blk.9.attn_v.weight": "9e708f15d332d7c5187b0693b1a977eb30a2fa10bf7df48ed9d7537c0aa6ed99", - "blk.10.ffn_gate_inp.weight": "97503a5d166c1925f9b65c0eed980753d411714d66896f3d0fad5286c7aba702", - "blk.10.attn_k.weight": "1ebdd222336bd25b48df1b138cdbe09021c4a5562ea7cb78cadd1255d2be3a39", - "blk.10.attn_output.weight": "5e98faa38e9d514b9057e1c8342c509cbe1083defd518e506f6bad89117d1f5a", - "blk.10.attn_q.weight": "3323a26c87d936d1dd87c577d0b763459fced726679612c874b3de5fc6d969c5", - "blk.10.attn_v.weight": "d5fa73cb56aca388e205f44455e4b4f676fdc12ed7fac4542fbb3b41ecea59ad", - "blk.10.ffn_gate_exps.weight": "225021b53782800906cd13b70be3a4161e8b300b97f984a959ccad6a6e8adcbd", - "blk.10.ffn_down_exps.weight": "f08eb91526bd22f5fd0402fe925d6141cdbb308a1ced0330858d0c85c71f5ef3", - "blk.10.ffn_up_exps.weight": "a9f688350c3b53eaada5103b5848bd9a3d7d6b327a70fa16c24bf28ece933eac", - "blk.10.attn_norm.weight": "5ba426c9dfc79805015ccd76cd1068b0ad3bb7a8453e14bb1d35486f122d8f95", - "blk.10.ffn_norm.weight": "98891d6acbc3986b2581b7a3af9f5946a392d9188972c6a8b15d4e745a4f2482", - "blk.11.ffn_gate_inp.weight": "b2365a60566e7dace892e1cb0e62eb73ce387352601723e847052b34874feaa6", - "blk.11.attn_k.weight": "0efbc1d1430505543ff71532a4fcda821aeac616ef6c1dca40e00d4f2ff70bea", - "blk.11.attn_output.weight": "3d5bd4d9a41236f30d4293edb9ae27beaa113ffb31b4fbfadff3a4c370dfd3e6", - "blk.11.attn_q.weight": "aa11e9db14dd9c77951511443077c2a1a78070753d7bd3d9811038473f69e325", - "blk.11.attn_v.weight": "5adc567f377aa11d1763d35f50e53fb2896a8b03b623ac36acc45efa2486d512", - "blk.11.ffn_gate_exps.weight": "71d07d982aabfab9eed3c733d49c20f023bf475368fc71db5084d91beadc4b47", - "blk.11.ffn_down_exps.weight": "9a06e61461e48b3925a9f7d9cca634d048c8b62163d7bc5c43e35899f959319e", - "blk.11.ffn_up_exps.weight": "bc05494d0dcec61021b3ac0c5bc1bf502736cadf48224e213bc139d562699a89", - "blk.11.attn_norm.weight": "a5758a10bdd0404ae1470e8e9db903985d4d07f60553c5001a5e7b660d4f7ada", - "blk.11.ffn_norm.weight": "814ae037563aad3771787316bec4806c95bf6f5991dd6474b4b1e5cc13dc18ee", - "blk.12.ffn_gate_exps.weight": "3a68b831ba1606fb9ef6dffed4732032447ecef23ea563ff4e79317586c7eb49", - "blk.12.ffn_down_exps.weight": "268b25e13f4b7beab08686e83705a41b21d15251809ee4784526f78a580da829", - "blk.12.ffn_up_exps.weight": "9105751a5b5b42ca2614d0456f24f779d2e2ac8cdff0f96842aa7ae2b70f341e", - "blk.12.ffn_gate_inp.weight": "d0de1558cc1d458c5c504f63ddc59785c323df7330474bb0644c346104b40a3a", - "blk.12.attn_norm.weight": "859a4c8113678e2e202d10299850e0cfb52eb11ea50bcbf4fe3ff39bdd394154", - "blk.12.ffn_norm.weight": "7fbf4c459c1760218877e9ee3f5ad49e960956a4369bcfe96c143f04ff9ddf97", - "blk.12.attn_k.weight": "0a7e254fdf3730a57372b6ff421a613eabaea68cdefd64800857941411318374", - "blk.12.attn_output.weight": "ceb763fc15d88af149d8fb78e82db2b7dab3aeae584af8cf7611a12356a397e5", - "blk.12.attn_q.weight": "a43402d23c46cb2d3cb3c2a98c81b19d10026b7e6742370fed6b2880b6e049b5", - "blk.12.attn_v.weight": "3bc24f2c0480ce91ef72993ee8f1cf962f7359e12183424583ffa1246bf3db52", - "blk.13.ffn_gate_inp.weight": "a6d68c82bfe66d8bab68f980f5f18268a9e2c0cd6b8832ed39010e0de198ae05", - "blk.13.attn_k.weight": "0166c39546b37dc2e01b2b396ba43e183f797dd04eaa51a6d103d8b58ee4bace", - "blk.13.attn_output.weight": "2ce5eb198deab9557475a58b69b11e9874b547e05c23f223c6e42fa35ddca069", - "blk.13.attn_q.weight": "745c1bbdf434284a7fae98f45e821c076dd9c2a2467dba6a9d8cf0041e419dbc", - "blk.13.attn_v.weight": "9ece68d5ac64d1421ea7aa32e1cff9cc1fecf5175f4c4da858dd31d8633e3337", - "blk.13.ffn_gate_exps.weight": "ccfdcb4670b131689de12d396a010b5ea737795cf5c15a14a304d720b3c7c899", - "blk.13.ffn_down_exps.weight": "8b8fb328664764f1aaa5cbdec336d5654e981e965a02ef622bde5f07ea1c164d", - "blk.13.ffn_up_exps.weight": "d2ace0236c2fb3365fdc85499d676a7f65813c48e5085348b1df1799922766ec", - "blk.13.attn_norm.weight": "1ed29d7d89ce52d7cb4d57e895ff7115430466e917136c049c385c030ed44e9c", - "blk.13.ffn_norm.weight": "a194fc542597a4dcfdfaec5e3cba2a2b2b21b21edfc87c39c0d7f7651355bc4d", - "blk.14.ffn_gate_exps.weight": "a625e3574e5e740e7f8e2f9c40390f2f382c720aab5b10534e298002dd8d1fb9", - "blk.14.ffn_down_exps.weight": "bc366f015b83c865946afd74c8a884943e0ea2c671314a0b7bb72f21a44d2f78", - "blk.14.ffn_up_exps.weight": "ee3199bf2086de77b49f57f487676be8ee70e102a2fb5a5ef8ddbbc28a9eff41", - "blk.14.ffn_gate_inp.weight": "2b437870c850fa2e2044d032bb02908af634356e37466fdae260b933e48ee8b4", - "blk.14.attn_norm.weight": "cd8344d193a1cbd42bd898e17f4bcb1ca0b2918420fbdafa9249a6f2b7f4ae06", - "blk.14.ffn_norm.weight": "70eec40374e558fed5b07257283cf36342b6b0129285a00007deb59c32c9f7c8", - "blk.14.attn_k.weight": "4053bdb507e0543d724b632570bac86b31707696d90a0db44c49b2a082e0d599", - "blk.14.attn_output.weight": "0182632cb0e06a07241b8293d25d109fbc1862e1e337d435f908e8681e2eb1ab", - "blk.14.attn_q.weight": "ffc7794a4c1b6f793c842dba969435330a7a80b9212e457b4b2ac33e68b41241", - "blk.14.attn_v.weight": "6411805292d528e61bbaad8f9aab9dd073529a17946c057fb06864fad9cf3211", - "blk.15.ffn_gate_inp.weight": "77d0744567c76e6abb67f81ba9c715b2b544841186d5b948309571eff213bafb", - "blk.15.attn_k.weight": "1f7957954ea4c6521c257b35a360e868ffa02bdb3de91f146d5e06bb4a545c98", - "blk.15.attn_output.weight": "d7809d36bd8d3342240c46fd87bcc7f9821a222f48d9a95e45ae50460265d3cf", - "blk.15.attn_q.weight": "25f509313ae4d8401b871904059f472a26f5714e7c791c725de77a1a522c976e", - "blk.15.attn_v.weight": "96fedf5a591fc0f020e6de10fd72ff12b3ef9cf70cd21dabaa0d3e7b06f54e73", - "blk.15.ffn_gate_exps.weight": "8f950d976b2fd9a3d213b84123cf114c1377efde9352767fb2ddee89e177c8ef", - "blk.15.ffn_down_exps.weight": "6fd09d1557bb94b06efbd4f6a1ca4be532a202ba290e9315bc8da3d12a5c4c4a", - "blk.15.ffn_up_exps.weight": "cbeb59ae7b0266a928dc7e3a6e70a9330b92f9ee1b17ee1ed91022108204a33c", - "blk.15.attn_norm.weight": "2005330911ac2edc7b6d27aca021c67d30d16eb632e49b1a13f30fdb2717aed0", - "blk.15.ffn_norm.weight": "0e9198f3b548eb78acc8961f2b3350d238d26cec110933ba753a8cf0035c501c", - "blk.16.ffn_gate_inp.weight": "a41d1f99d739c8b150c3945b6949763988d0c6a4c5a2b5855592ca1a48ed23d5", - "blk.16.attn_k.weight": "b624e2ec88c2d3047f60530fb87e72cb4a5e655a9663f6f3e9b09e5ad32cddaa", - "blk.16.attn_output.weight": "687759ea75e45108526ffc1573d6fdf084728079bfc2dc89b9979e76280f43c4", - "blk.16.attn_q.weight": "beff3a45c7e9ec82ffc6d3c701126be28654d10aabd747d03441210491fd31b6", - "blk.16.attn_v.weight": "43a349b13f0b9d040cacecd942bcb168c030fef8c75c987d59a4fce6c14e855b", - "blk.16.ffn_gate_exps.weight": "793406d6c13d727c82bb7b692ca98d65ca975baee69fc57be5378d77c5a19b62", - "blk.16.ffn_down_exps.weight": "9bad3dd150d0230404b7f886ac7ff8803225757e813f195cdb26bad245243b4d", - "blk.16.ffn_up_exps.weight": "7449d663023fea3496475bf0a9c1de7272ad0ce9adcb3265e8e424badaa674dc", - "blk.16.attn_norm.weight": "a424ce34c195a401df1ce37ac4f2794e8a6720b1ee8acb21428e2b68c65e0125", - "blk.16.ffn_norm.weight": "405a68bb8e16e1064df2de55ca3cd9ceddda1d9fc0af007a9bd7cad4b2676248", - "blk.17.ffn_gate_exps.weight": "97c6e5321491ca5dc039ee88da0eb0e78f347372785411809af84b3298cb19dd", - "blk.17.ffn_down_exps.weight": "1617ac19788a1be19bac69277408761e6bdf5719d63a8c7fea14d41cc27641b5", - "blk.17.ffn_up_exps.weight": "4ead1c365f112581c10610ea3f63d2a1474311d2503d2060fed4b458ef337f5d", - "blk.17.ffn_gate_inp.weight": "ed4b3393f2523f2b5e0fc7680a1caa2842e605728a529b5af68a7fa8d7abf940", - "blk.17.attn_norm.weight": "beac17ef86a7fb2b5840cc72f7a95a5e3d6bd24e7fa698e0b0ebb9bdac45c561", - "blk.17.ffn_norm.weight": "81cb58ec6d6dc02a0b4ede10adc336dc865fa76f982d4eab0e4a37b40f5b0fac", - "blk.17.attn_k.weight": "eab569e5ea8c8b05e5a6a209fba031129453c2e28181eee3e736b3b04b36bbec", - "blk.17.attn_output.weight": "f85b70f01438ce8fe5d10599b113f30bf18dee2bbae0657d3eba295870001db3", - "blk.17.attn_q.weight": "887ceebfbf6a2b94b43d2df4439ac3a5bbc29311d4b28addc04d525546032047", - "blk.17.attn_v.weight": "2df9414d65014c06a93da22ba3a668be7b83e2e8008e98d7771f7dfebed98298", - "blk.18.ffn_gate_inp.weight": "9b07741a0950fc667e5fd25937e33bc22e1f764f80eb4ff3119f005327ae0f6e", - "blk.18.attn_k.weight": "8649598dbb63938744c39bcda5ce8c31773e29c573be8d4d2c114f5030f8d3e8", - "blk.18.attn_output.weight": "f8e391adb92622298ca834d5d1eda48b69c3b1c51c5a584ef6c54a725c298d75", - "blk.18.attn_q.weight": "84bf8708a2eed618f48f69c178ed7dd11fa4c468102376e72e910ebd037d131f", - "blk.18.attn_v.weight": "31db3cd773f09548c2c1b1eac2718e46364a7810970fe9c433fad9d8de5397eb", - "blk.18.ffn_gate_exps.weight": "be2a2ba378002f1b61f86c273a69eede9b93786d5ce96b4fee1861f730dca4c4", - "blk.18.ffn_down_exps.weight": "d35196159e37705db50a5343e3989f7335477f1a4add67ef42ad64a638cd07ae", - "blk.18.ffn_up_exps.weight": "c6ceedd86e97913a6dcadc838e7abb762d629fb8dd55f15cf02fd9bd66d2ba78", - "blk.18.attn_norm.weight": "41f0b1ad83d6e3cb9fbe0d27878c2e7ad4a351b9f554a6bc9117c01745cdf6e5", - "blk.18.ffn_norm.weight": "96646204bd0d82f25dc77faba4dbd86b1332e449313e6684e00122da8be99057", - "blk.19.ffn_gate_exps.weight": "c6eb7f61e7938bda0492dbc05e51e8f631c99224fe18e99861fc4fc53ba9e9ff", - "blk.19.ffn_down_exps.weight": "4384803da3a3a3d44120d7dd192fe2c9bbd9a1a0cb492dbec1fdd7565230f1e8", - "blk.19.ffn_up_exps.weight": "22d73de2fbb8bb0f1bd2caf17fad8a355c47d914143f7f6e6d0128f66f074a60", - "blk.19.ffn_gate_inp.weight": "9a0cc4a2301a5634022fbce41189021bf0d1a961792d2d9330fd35556d18e5bd", - "blk.19.attn_norm.weight": "c5cc56ec5df9a1f7d5ad71fbda49f1433132e58895d45cb44c73420bd61ebd6b", - "blk.19.ffn_norm.weight": "77e17de741742ef2482fc7872fd423c8e3c1454dc4d2be89ee939084b6d78bc0", - "blk.19.attn_k.weight": "a92ea36ce2e3569656306aeefb835ccd5d1b03b33a86e0d3d030644cc923b813", - "blk.19.attn_output.weight": "5e2a912b37855f84ea964907a1a86d609cbdd79efa0c93c3e8e2fc07caf7c226", - "blk.19.attn_q.weight": "4ef3a5913292ac3c1a6fd3e9e53d011021f2b41d0276cf849706d1ca925cf7a7", - "blk.19.attn_v.weight": "42981b75b68ae852cee638b5433605c147da4392aaa6d7a06e756115b0171f39", - "blk.20.ffn_gate_inp.weight": "71381b9879a7c80b9f7b475abc0aa31b8cd71ccc00856ebe89764a2acb9df2dc", - "blk.20.attn_k.weight": "1928b7ebc054eb3967929ed6fb446314d5352f4aaf8b475ce55c6345019f2ea4", - "blk.20.attn_output.weight": "6071ecd9ca91af0d2ba93fef4a1a56f3b243dd70f862a21a2d164d56f386043b", - "blk.20.attn_q.weight": "002e95042a40f36ceed5829e3d0c8072e5f5e4ee86a089e2902b2348fed24dd5", - "blk.20.attn_v.weight": "42f509cdb1c0e298f89f896e349be86952c5168e49b3f83bb17badbcb7596d57", - "blk.20.ffn_gate_exps.weight": "a684a3ffe4b0a57c819a5fa9cb3521de223f392732927271e97ce925b6e33765", - "blk.20.ffn_down_exps.weight": "e3081a7bc7ba750d8a4886bc8ca4f231b55db4ca082b54b4106c7531964725cb", - "blk.20.ffn_up_exps.weight": "fad0fd5eca36ab154788da28be8ec25bb5d6db06c9d133db89e96df358a2f6a2", - "blk.20.attn_norm.weight": "c3e3f2429715ae95e884ef1246b0b461b23c5cc0ed08beecf70a14cddd184820", - "blk.20.ffn_norm.weight": "ff31f609dda65ca496b0584fabea6550e42edd05ebf229812aa6b7bb5ede15e6", - "blk.21.ffn_gate_exps.weight": "366f09ef0ecfb86808eb3296cc9abdb957951d27f6533c03f1422b54061da660", - "blk.21.ffn_down_exps.weight": "3fc495947d27fcca7fc0893c8a96e5d48ba27b2c8c58f8fcfb8dcfcd5539741c", - "blk.21.ffn_up_exps.weight": "6713ed51410bcc8283cbb001c4ad784098f25701e8021f4fa4f411e186859c4a", - "blk.21.ffn_gate_inp.weight": "6d4c92c01ec801647134d907bf1108878156df266a6107abc10526332b328b93", - "blk.21.attn_norm.weight": "27605719ae2df24f4f2e85a730927cab20367631612cb501631f6bbf38eb1209", - "blk.21.ffn_norm.weight": "ca80ee8177db185b15a4a378c1cb6f7143c76546a7f1726bda23f329323d4ffa", - "blk.21.attn_k.weight": "9e49f743d4a5bda9b4bd9c40c2ca37cdae5aec7e54cb193897ac8b4945ada14d", - "blk.21.attn_output.weight": "ab923540879753feaed152f5950f69cdd83d8f2413ca873f5f038b63ab0aea12", - "blk.21.attn_q.weight": "62617fc3f1c9d2aa672a4d91a121c7a91b92d145b65e75f0b06b4bb7c825dc36", - "blk.21.attn_v.weight": "15f8b2e72f8e8e992f2f6b3e93238a9d7be7bd6136f91c9d04b4b4cd0cd60369", - "blk.22.ffn_gate_inp.weight": "3ddb1773d9257b68add7a2a4e94dad25ed926803e02707863dd742ab9b2dc179", - "blk.22.attn_k.weight": "680e45a9e8d5feddee5266e119dc053bf80718fa9af1cf6803e6f493b265f1eb", - "blk.22.attn_output.weight": "0d5fae3402fb2c5aa3a860010e3973fc8e3168d1015f7a76b7b2964681693206", - "blk.22.attn_q.weight": "eee7e3d426ab533bd18d62c9aa142eedbde394bed07db58313e0fccc82a23237", - "blk.22.attn_v.weight": "26b5be1fe3c2b6824c5a648a3e4bdf17691904526fca158fbc3ebb627b67e2f4", - "blk.22.ffn_gate_exps.weight": "32ab7a7735313d60f6a75229b1aeee940b6aee176c9648536bf5921b0dc2929a", - "blk.22.ffn_down_exps.weight": "67590808f6a67777d3eb7976c31fe616d388b98fecbb12253b72d1241d70753f", - "blk.22.ffn_up_exps.weight": "fc245c0183e6d90829ff5e71a4ec93e4860b3d4c1a17b9dda2fb64f5f5c9ed32", - "blk.22.attn_norm.weight": "128e99d206d4d6724758ec97468af767fa0aea592149c324b731659c1e74a1a8", - "blk.22.ffn_norm.weight": "e45f498033f0cffa15da0eff2c47b4472e43fcf8921729fc4eeb2e3a6b3c78e2", - "blk.23.ffn_gate_inp.weight": "d63e686f5325fbc89fa242c2c52a3b8ff54f867dca914c9ae6eea13e9d6f46e5", - "blk.23.attn_k.weight": "f71f5a577f46ea12b1818f3a5ff4b85ddc45f9a2afb0fa2e041d71a3e31c6779", - "blk.23.attn_output.weight": "92b13563c1e0eac0d748fb67b235dfd7a64c8f16e2dafb316885744582e23b4b", - "blk.23.attn_q.weight": "2f9b9c35dc4f912f3f51c06e2d68f417b51a0de0a84aac530a64f9d3d7b0a2dd", - "blk.23.attn_v.weight": "268e40813806e74a5c364b19556d087bf8374e76e7b6fcf55c381eb7da13ccd1", - "blk.23.ffn_gate_exps.weight": "12f857e7a7ce228afac34d99b602c8d6fe96984f2a21118f459a58cb767ee65e", - "blk.23.ffn_down_exps.weight": "cdb082c16599c3bb36a28066dcc122d9529b54fa91b6cf0153437ec960a5e16d", - "blk.23.ffn_up_exps.weight": "f4b99f6f44d7b8b5a305894e88633bf5938fc1f6303a2b2092399da9c8b64d7c", - "blk.23.attn_norm.weight": "a691392210383915916b4d3886d5e4d56e7855e27e37e414fbd73bf66b3712e6", - "blk.23.ffn_norm.weight": "0c3dc72f667e5ae19b69bfa9f2bd2a01a57681f89ef9527bad4eb0d8c7b70da8", - "blk.24.ffn_gate_exps.weight": "86baca2a3157994df7fd8ced5e08436d5c1810dc29c0715637c36de723e0e7d1", - "blk.24.ffn_down_exps.weight": "ac5d559562b35c34993e34b071f66d15c65be5907797078c2d2a49aba54e3192", - "blk.24.ffn_up_exps.weight": "fce0a099cf09777f44fbab3606ceb75f7fae6f0b80725f9e871654b8cdf9262a", - "blk.24.ffn_gate_inp.weight": "e7c6800c0cfc56b565b2d35ad6f1dbfdb70dd0b05b338bc8da2286ffc3678d79", - "blk.24.attn_norm.weight": "dc6cc18ec52d102d015153c4a1132f9d7a504e29cbdec81c5edbf3b9e65815e1", - "blk.24.ffn_norm.weight": "480d5a1397af5e0e657f1e67d20ec0cdef5724e71246a326843321b87ffabd33", - "blk.24.attn_k.weight": "338c0597954a9b95a782545b2fe36469553e73f86ae2d2b5697767b28e1c7daa", - "blk.24.attn_output.weight": "a77d23b79933c67e52f1eef7f83a3dff4f767ce0bbcc39572f8cec4acd457643", - "blk.24.attn_q.weight": "45c9478593002be1998e96e70668aafa2dd3972380fbc1df12fb05c24ba959e0", - "blk.24.attn_v.weight": "515729420885408a6a9614bc27cda393ed907521318d14d21335d39a3eff0b61", - "blk.25.ffn_gate_inp.weight": "aae4ac40e9ab3925241f9d784b54b38851d9bc999a6c3bc03fc3f17c9b28a67c", - "blk.25.attn_k.weight": "4ab4808d02396c35b00b426f536015673b71c17ae6cd55bbc2e6bfe7a4c59d0c", - "blk.25.attn_output.weight": "1990bb982b77e0c947cd1a8ef0b36227ee1259e6dbbc2829e5c136edf88675eb", - "blk.25.attn_q.weight": "a1490f3048e8c0ec8784f8550c43adf5cc8d0f2f90131c934713fe4b1b015bd7", - "blk.25.attn_v.weight": "f15e53c6d45b3b6f58808fa968425d65e0b26b7f9b268127a77abb1227c67431", - "blk.25.ffn_gate_exps.weight": "656662447ff54f56ee80f78a1b9483f7efdc40f7375d0cd8a9c72ccf21f77e7b", - "blk.25.ffn_down_exps.weight": "db06f101bccbaef19cced0f6c185166e18202465f4a42cddfd535fbe5cbabb4a", - "blk.25.ffn_up_exps.weight": "584a7b02456f27fe1d8d3c7ccd21d426b6ea887795a3ed77f704596a1e3841d7", - "blk.25.attn_norm.weight": "8f0f3597982930fd237e9d609776c64f2b909a455b21678f83a7ebd4bbb83e64", - "blk.25.ffn_norm.weight": "3e7079c32582afba0c55e032f254adc18d2997705eec860185e9a6dd3d82f07e", - "blk.26.ffn_gate_exps.weight": "e70341691b583b86489812b29b77aa41eb658b1865733d6118da54c66e3bfcc6", - "blk.26.ffn_down_exps.weight": "5c1b812d11dfb064af816ced5ab6463bf9722eefdfc341b8a93705d5038fd781", - "blk.26.ffn_up_exps.weight": "e18118362ae54ef7432781c83884f9fb230a9d934e342aabeda8822ea5f71fb6", - "blk.26.ffn_gate_inp.weight": "cd1c5f6710166b9567c6b74c97b2348b191c60aa860958c6bc264ab095261dff", - "blk.26.attn_norm.weight": "71d087531af2520bda2e676c489e8529cef5db8aeea1eec0a937a8b4f2fa2e54", - "blk.26.ffn_norm.weight": "7f704e936fda28eb5c2cc339f0f6a5f78170b5aa43c01265b21668870d819c82", - "blk.26.attn_k.weight": "1cc62a0ce0ae251275d898c52c4a9fba5995fca10955d2011d10dd1a59e1afb8", - "blk.26.attn_output.weight": "636e881b1505f9cef656a4be98bec6a4765321d51f9bf1dac8933397cf44b765", - "blk.26.attn_q.weight": "89a3c4d202d7d6adebb9e0c1bcfd8b775f6456386f1be25e86e43acc949c1e16", - "blk.26.attn_v.weight": "ff2cc963b597cdf1a21703f3e7022af3bb4c65a34a19e19d9309a7c5e198b5bd", - "blk.27.ffn_gate_inp.weight": "6150139498fefe380bb99d11e72028da47a15ecb73dfc5b2774f726f4bed8f9e", - "blk.27.attn_k.weight": "f286eb9e5c56c7b801a497aedc40158c2a27877d7f9fb59b3fc67834798902d2", - "blk.27.attn_output.weight": "5dc3d3a05f9f7729509147fd09c16fb53f85f520cdab5cb69abf4bae3fd460c7", - "blk.27.attn_q.weight": "8462e40f86b24251960d6f35a9ea99b8793a01937faf1aec2859f2e5395dbb61", - "blk.27.attn_v.weight": "bac1a99e38e25953f8315f7212eb9777dc216cadb09b959977885ae62724ceca", - "blk.27.ffn_gate_exps.weight": "6a15eca7f0f6ecfd93db2e55c63875348ec4a78c4ff643ec46df9e958c0101e4", - "blk.27.ffn_down_exps.weight": "2e1c91247c4359e2073a8e5f26fd7f6426da7be3ed5bc65dcfff701f0a5022b2", - "blk.27.ffn_up_exps.weight": "65d6f5c553c9332085eae4aeadf25090b5d7768212ea7b08ed698102c21b29a1", - "blk.27.attn_norm.weight": "7fab8ae63ec8e91ce625cd130ab96d8427dad3a7413bb21b25ec5f408c5b9f5a", - "blk.27.ffn_norm.weight": "532720546b0fdcd423a02ca6e3e9d8aacb84b1b3e8269968f88a47fe2a69bab4", - "blk.28.ffn_gate_inp.weight": "a305ea58d98962d9dcf0c53ad2389b7acc8936fb35a0e3fc9410e7767cd49dea", - "blk.28.attn_k.weight": "8315e8a2e4f78dfdf36d4fc18fffc74bc95fe42c3ae4f9af2b6c874612c0f71b", - "blk.28.attn_output.weight": "9b5fdedd32d39ef46a22cca7cd5355d7b93bd07ea305f466a8aad6ca5a4f3778", - "blk.28.attn_q.weight": "4e8fb96997c30e231c437130f410d7c91d541a816f6c568b5f3bfdb4b8dece74", - "blk.28.attn_v.weight": "1fec739cf3bd7b4913f72ca358d4cf31391c304de44ac0ae31ecb825beaa7cfd", - "blk.28.ffn_gate_exps.weight": "9f259789d535e09268266b9a8020f32d6a6779966c909d91d3a10574f06238a2", - "blk.28.ffn_down_exps.weight": "516d3f8abaedb01b9916a4b67d4672159769138ef2850158bc1b32c41e31f0e8", - "blk.28.ffn_up_exps.weight": "f2f1d88d2c31ed588806fb5ad981d68f5134d7284c4fc022fd018de2eef437fc", - "blk.28.attn_norm.weight": "960fd005598deadaebd969996f4367a9dbfad90539a863674fe95730935acc64", - "blk.28.ffn_norm.weight": "e1993b37ced93d4049e9af2c47b0d9207d8f7e6f2cc3a52f57bef30bc806d805", - "blk.29.ffn_gate_exps.weight": "58927146338f443513337476b3cd30e6341742f096c2beb5890d400f10121298", - "blk.29.ffn_down_exps.weight": "03a3386e4f0b75a28c5608e23b2de8f0de25f21954e4aa7fc343431bde9db07e", - "blk.29.ffn_up_exps.weight": "6916b7490a7ae7b04a5d81cc1e7ac9b20c483434f3b186b12d87fe176bf1567b", - "blk.29.ffn_gate_inp.weight": "98e710e467a3d567abe4ce29d78b8e8dc033148762290c0c5e1ae4d78efd8c78", - "blk.29.attn_norm.weight": "4e64cb307d37be20d55f38c94faf7e451d11df5e60df347906cbaf9c5441be71", - "blk.29.ffn_norm.weight": "696c23a52f742679bd44440d687a4c44b4302d57f1e9dc5610d23374336187e7", - "blk.29.attn_k.weight": "e85253652fd6120c623634ba66b725bf7cd491318b54ccdad2c7df8851d64c0a", - "blk.29.attn_output.weight": "4f650a71efb150d1f24cd4d114d4187bf570ac424da3b92ea6455abdf1aea705", - "blk.29.attn_q.weight": "69fa7da901026ebcbbbc848455b425458b7e3295007d7fc093acf4b38e2166ea", - "blk.29.attn_v.weight": "17e2e7590b317b21f106de546aafd955579703d1e95d6aea044ee72ec3a514c9", - "blk.30.ffn_gate_inp.weight": "3a03284b4aa60d59d4a2ec86253469b61fc656372afca427cb77a5332fbcc62c", - "blk.30.attn_k.weight": "d518cfd0db9708e769eb1399e87ee49357dc54d5afdbac3d4c0ca46c64e789eb", - "blk.30.attn_output.weight": "9b44378714d784c5ef9ab604359091baca4e0ec222afa139b7f840eaefb371fd", - "blk.30.attn_q.weight": "cbb95365bbfbcad0c9cd99b4eebb5a5d32de68ce08e4063b5ec3e792b7548044", - "blk.30.attn_v.weight": "e7985c04fe1740e35a9598f43b67b0922b4fc2d00b68a92a9f917b82c3248de1", - "blk.30.ffn_gate_exps.weight": "8ac4bbd07935d98f895ba94dc174e5ad5046c3c222b53729d60f987c05e7eb70", - "blk.30.ffn_down_exps.weight": "dd672cc71e82abf05064a18121b8e55fe1a4f19bc1d7cb9a142f4add54bc336e", - "blk.30.ffn_up_exps.weight": "12282f664a2a12aa25e2deac58946108715ebb978bafed5274cef24569107646", - "blk.30.attn_norm.weight": "1a33458fee054c6c9c896a4bb0a4e1fbfa0293b2408c7dd2b81d692e966e7273", - "blk.30.ffn_norm.weight": "311e33b68051f507f1478ed8f2693fddb846170ddb7285a91be43f795c2ce31e", - "blk.31.ffn_gate_exps.weight": "8af43d9867a51cd8392fb48b981b0ceee0ae979c491c07d711b3b56b5162c786", - "blk.31.ffn_down_exps.weight": "5579cb7758c1600b19d1f540deffe081b575962e37437b3b2efb2fb0a2924e40", - "blk.31.ffn_up_exps.weight": "f2e7c005276b3a001fb40753f027fa10b4d5a346f43cf4b4bbdeec6e74e1cf6a", - "blk.31.ffn_gate_inp.weight": "89885dc0e30b6b16a90c0331d7fa3174671e941364e8102d934f02132237e61b", - "blk.31.attn_norm.weight": "99e4e9bf86a9edf8c404153a7e8a82324ba79da462622196e2faba161bd95172", - "blk.31.ffn_norm.weight": "55335997cf6de781bf332b943de96ff4646966b05d9fee86b76ea897e27b6ca7", - "blk.31.attn_k.weight": "cee570762b78da6316b637892cc4b080e40f57af5551ffb1866b9a8e80e96628", - "blk.31.attn_output.weight": "fa321ff55ec7819ead7b819fd45215262f39744569765ba2113c989c03588802", - "blk.31.attn_q.weight": "9e2c409b878f8a2a1436874abf428fceb1c534b21f9ad4dd6f532b8a469007f0", - "blk.31.attn_v.weight": "a845d0be68ba537b4a775bfba4d897faf7c82a811a2612b0b7420cc4f3574cb8", - "output.weight": "16101cbb74b54cda9ebc07ca3c762e3263a56efb3cc011156184b95807d7cf13", - "output_norm.weight": "d7aa61585baedd60157aafe157930785742c55989c288573566a971b02423564" -} diff --git a/ollama/convert/testdata/gemma-2b-it.json b/ollama/convert/testdata/gemma-2b-it.json deleted file mode 100755 index 0482f1e..0000000 --- a/ollama/convert/testdata/gemma-2b-it.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "general.architecture": "gemma", - "general.file_type": "1", - "general.quantization_version": "2", - "gemma.block_count": "18", - "gemma.context_length": "8192", - "gemma.embedding_length": "2048", - "gemma.feed_forward_length": "16384", - "gemma.attention.head_count": "8", - "gemma.attention.head_count_kv": "1", - "gemma.attention.key_length": "256", - "gemma.attention.value_length": "256", - "gemma.attention.layer_norm_rms_epsilon": "1e-06", - "tokenizer.ggml.model": "llama", - "tokenizer.ggml.add_bos_token": "true", - "tokenizer.ggml.add_eos_token": "false", - "tokenizer.ggml.bos_token_id": "2", - "tokenizer.ggml.eos_token_id": "1", - "tokenizer.ggml.padding_token_id": "0", - "tokenizer.ggml.unknown_token_id": "3", - "tokenizer.ggml.scores": "0872465d173867d755d3ee728f882b9dc2057a0bfd596fe1e3d131522f1250d8", - "tokenizer.ggml.token_type": "485e40bf3d715a4764818fc097d6a2a41db872d82ee714bc500872a3437ff48d", - "tokenizer.ggml.tokens": "c6e66de1841f04de8b8d236d461ab720a4c9b9b5414dc293a09c6e10eab45fda", - "token_embd.weight": "17b87ab2c01c80657855a5413d0457b4a041afaeda0cc785080e44e2f04acf07", - "blk.0.attn_k.weight": "28ac0da05754ad2714ae95da28a5ad191192140b30b8fd22d108d4700c9d989f", - "blk.0.attn_norm.weight": "3f9d5675d1ab0eb8a816719dac9fab81f2e95c52be02c34263339acbc087febb", - "blk.0.attn_output.weight": "703295c2c63990ff896778685c678f145298886f680f3ed5dc2a7ad54c293265", - "blk.0.attn_q.weight": "69c2d0e4870e9d722a190d356203c9605575a16863466c3d1747966ef1cf5791", - "blk.0.attn_v.weight": "95219c9c07b5ffe9a9a01e456d845eef2b11f4fc12c93dbbba479db395444c13", - "blk.0.ffn_down.weight": "a2feb5eb3d572c57c5bafbf0ab506862df1160fe40965dcfe4b9fd855c08bed7", - "blk.0.ffn_gate.weight": "fcca072c445c31f4dc4d5dfaa785b1bdf7271342442099b74fd17268b5829fbf", - "blk.0.ffn_norm.weight": "7621f95dbd245cade6fffd6b08797d69d8e3954e960f0b5551b90d967ab95448", - "blk.0.ffn_up.weight": "14a9bcdd451403c67136391e1b6e53b3b1830f00199bd911dbcc56d8749c14f4", - "blk.1.attn_k.weight": "c70f73c5df20579cb44d971164b48b5f0d8d5abdb38b381e7a8b880ba12aa406", - "blk.1.attn_norm.weight": "88b6b91f93a1ef83425a7c7dc2a2fbd3b22704a04c64a80061df376ac8c33626", - "blk.1.attn_output.weight": "f031a537490c452be3b3bb51e6b7949a636405756e160976a1c070a792ea00ee", - "blk.1.attn_q.weight": "bdb23214b1cf9cfd30f863a0a5868e52c6809d93b7e8f44df096a94204d9896a", - "blk.1.attn_v.weight": "e9bbc0b05f2c872fb1403f8f938cd1612b502229ee401f12593b1164c61acc00", - "blk.1.ffn_down.weight": "5ff53811038b661a7b8f2bfdf213bebfb185ec1a6060b662f063714f33584d79", - "blk.1.ffn_gate.weight": "205085c8c951a5c7543b1495183cd96028fb49f67464b3e9862a2693a6077a33", - "blk.1.ffn_norm.weight": "798f354fc85afce9625f5d10093a585a966831698a0560e6c9b97ce659eb4b22", - "blk.1.ffn_up.weight": "db92dc5684cb6e90940e13f4d1da555ed20ba4f8cab1e990ddfd7553e2e91315", - "blk.2.attn_k.weight": "ef5ce360c4eed6d00d03ca4761e0f8e4b0af4509978468314be14f3d46621044", - "blk.2.attn_norm.weight": "6dadbc05dbd0d3fabb4216affa60a3de1378a82d2859dc90b338cbe70f50d455", - "blk.2.attn_output.weight": "6bbf87a966f691bbfd7c8d25629aa4e6710107bd431a667434861febb391edc5", - "blk.2.attn_q.weight": "4e575c09ae2de417ce9057ce8b073680e860a24aae13a472b68f101b760752e5", - "blk.2.attn_v.weight": "cd33f7f01141e9439afdaf2ea1aaced9feaa335e32a58daa136ebd555d4d96f4", - "blk.2.ffn_down.weight": "b970ff1b0b6494165defe2fbfa1d31425766ed71e64de9ec4e66ac3955c8bc5f", - "blk.2.ffn_gate.weight": "dbb3e1360402e0e369b101995bb686b73f95d4a7673f061be85d64d15dfb0061", - "blk.2.ffn_norm.weight": "bfb7980105d8ac9647710454f57a5cdac50598a0f6f4884e16f1d94b00844687", - "blk.2.ffn_up.weight": "50ef89339b275a438b664686f6227dd9b6e43853ed6856ec9e33ef4bbd90bda1", - "blk.3.attn_k.weight": "be942ea98151434eebcd2c1da4b00e0146152fe524a530689b1fd491cb833d21", - "blk.3.attn_norm.weight": "0df2f218daf609c289fb7c60c5f375fa99c0d4e04381ad5a494a19144edd8e20", - "blk.3.attn_output.weight": "c2184aaf86aa2cb8f47be49f60b165834e97205f39c6ee1dfd19fd4411a156ce", - "blk.3.attn_q.weight": "4f86e2a0a4221c1c84ff9c409ac89893cb95d7208cf65bf1e98e24e01125f991", - "blk.3.attn_v.weight": "abfdb8a60c349dadde641d1afc9542025e24fbf41a3238bfa9675e0b1f1e4b68", - "blk.3.ffn_down.weight": "58821a8d87008d47d122427911c6fad5272aca70c448bbae223256a74bacd07e", - "blk.3.ffn_gate.weight": "776e051f1a0ddd5c4934e69186683a75ca9a3c8c0f61911bba321fed1dd287d2", - "blk.3.ffn_norm.weight": "7f380f29335e28be90bfcfae6f6d69fdf5751211b36d2dd62aa5541ed113e4f2", - "blk.3.ffn_up.weight": "fc5ae8d488894cbd4951059675468d227da27871d26e925c9941863841c097ee", - "blk.4.attn_k.weight": "14833b078cc4c5137bdd5fdc0538047974ca147a99b0282e1b144440c78bc1db", - "blk.4.attn_norm.weight": "0a69957d4a15599fb80ad4753558020804925221457d9a5052926754d3768065", - "blk.4.attn_output.weight": "887a49b6130fb6297cf10767207c3dd97191b2cf63723449af9c27bca8dbeda0", - "blk.4.attn_q.weight": "51fd577b76764824dd6f0d4891c137ebe4736f591b5ca2793c5fff2be49abbde", - "blk.4.attn_v.weight": "1a623c43cf9c509d1b7ea0d1a5c04d0af4809665f9f9e93b7d6dba8c5df178fa", - "blk.4.ffn_down.weight": "5d61e8856d8941d2b1fd138116d015f63840d0fa1e31e20e20a5ceca1536ceec", - "blk.4.ffn_gate.weight": "06640f7273764f8ca5df7e386547417916b6cd7d565a8343153113239a94b0a1", - "blk.4.ffn_norm.weight": "91a6c6c41b894228e361435ecbc5058dca34d4911a23da5b56de219299c964d3", - "blk.4.ffn_up.weight": "d016dac1055e36d6a10b6317e57f98a904709ea892ef3194342f4d2f6326561e", - "blk.5.attn_k.weight": "987146afe124131500808cc0da33c06d207433656d41df6e6d8c99118a83bac5", - "blk.5.attn_norm.weight": "6b354938966f2608a2fb8d0f5b363ed0d8b0967c2ec8d0abd5c625b413042ded", - "blk.5.attn_output.weight": "cdcbfe02c6ff79d5326882b017a02099f5af71beedf6b1b3eb4de01e3a844536", - "blk.5.attn_q.weight": "b910d0cff781d3efb42eab0a302f46f286b2de717079175680d5b42bf8c309c8", - "blk.5.attn_v.weight": "66d3a279f747412f9f4b0e8abad44540c122ab2e811a7ee74c1f33bc36caade9", - "blk.5.ffn_down.weight": "c9b0efd2212981f16d956d8571f054b68780ad01f4917033647e359b557a4653", - "blk.5.ffn_gate.weight": "fe96b94109ca141c01f6a04788e20783019ca6ec334aa1f3134810bdb499e557", - "blk.5.ffn_norm.weight": "aa7b016e832e7055a36c6e20de58ea1936f995f390401fff1c5fc65906064e49", - "blk.5.ffn_up.weight": "555ce27c4873d3375394f38ad3b45e3d8848f9d5642dc1602383d0f0a33c2a14", - "blk.6.attn_k.weight": "88280d461db324c4f36475ce396793063e61a27283ec64511b0480890fb5b3b4", - "blk.6.attn_norm.weight": "af8f460c411f660d33196286d208f1845fd5a2b45f7b56549a4df31e7515447a", - "blk.6.attn_output.weight": "dd9996fb0a256e8375ad3917705258a33fce006bcea0f536caae420a77974d8b", - "blk.6.attn_q.weight": "7a4841541191e037cfb9b07930c4d8cab451809658b182f0ada6ccde9615c003", - "blk.6.attn_v.weight": "ae81e6a592b64d701a9d40233e986039a56cba8d8d24f61aea93c6393cf3078a", - "blk.6.ffn_down.weight": "622dd1ce1706355cbc659a8ab2c4509678ffe0f3ad34258e5e25ed2a5d951bcd", - "blk.6.ffn_gate.weight": "8389a735c0bd5591010f8ced9805a2a12c749f6df0d3c18ad4d05c2a302e7168", - "blk.6.ffn_norm.weight": "621f5346400382474d61358397bd58fb1459b07c53e376e4bca15e08b3f9b3fb", - "blk.6.ffn_up.weight": "8d834e4c42f13c251dfee36cf89e12f1bd400680d00d5c2e6cac0459e9ce2f7f", - "blk.7.attn_k.weight": "8bd0412de65a3e64901ef8fe6a28c95e116bf39dc9aa22f0126b9d36688e5ea7", - "blk.7.attn_norm.weight": "056d8e56be4e87d6dc6f900762f0dc6fde07bfdc50dd85bfc510415e2bba3f3d", - "blk.7.attn_output.weight": "27972eda51da53d416ff95aed78149a2c5a287b47d2cd46f2f544ca692ecb3bb", - "blk.7.attn_q.weight": "41eca977b9371f7932800c11a9c45b931310196919e2a0651b847703b180fc7f", - "blk.7.attn_v.weight": "13c74fd7e07f08883a09fb070a1fe5bbdd2341b4cb8d1cac07c4b637049b5774", - "blk.7.ffn_down.weight": "9e75db42468800849a9a7da603d0072c5e86c8ed2b4d8b20a312a51fb86a7a10", - "blk.7.ffn_gate.weight": "db6bdc3117f910088aaf7db51f2da63ea5bd933de36af5599c215bfb26f7db2b", - "blk.7.ffn_norm.weight": "48bb82b49bfc8679a1e77f282ee182d952db7a3c11be7ef9a102ee2ddd8011e2", - "blk.7.ffn_up.weight": "feebea87175817a0f3585ec0af09dc873d94c203581ae97a712eb356d3b49efe", - "blk.8.attn_k.weight": "d5640ad71b6af68d88e17bf8e7fc26c907d2262605457a84247dd9afc2884d69", - "blk.8.attn_norm.weight": "75b850c481a69083ae09d0207ba7317b37c735a39fcf5fef5400e6c84fb1257f", - "blk.8.attn_output.weight": "cbd669dbdea2bdd90f9f0cc97566b3dffff3c56cecb4f47290ceef30da83b2d6", - "blk.8.attn_q.weight": "9edcb63087a431bac361822497e6ecdaa06d9ea4a1a754e36da7ba9f8db81c7c", - "blk.8.attn_v.weight": "3fb72c2c4f95a83626aa3e30062f9450b09ab37c7871e229f18bbc5cf744633c", - "blk.8.ffn_down.weight": "bd69d2c9172974fff154441b237b4787fb53b2d185325442d5048130ef5bc4ef", - "blk.8.ffn_gate.weight": "d04689c80553edd011d1cbaa5d570fffa7fa91e88b66cf1352d89ab60b72f908", - "blk.8.ffn_norm.weight": "e49984183b735b7f2c4e4730c289eed9394056d2e283a00fd83ea0915df31a73", - "blk.8.ffn_up.weight": "8fe62a1ce8e847e567add6c6f6bf2922bc467495b5eb4c116b3cb85b85b3b211", - "blk.9.attn_k.weight": "d90904959e5004cf0d6e729c6bff18cc33c094798b802473c1ec55ab8d276183", - "blk.9.attn_norm.weight": "79277f290cc07411115d8fa138045edf4a17b3416ab2145409cbe8ab829fd4ee", - "blk.9.attn_output.weight": "5a21bf2e1f09a81405025f96d4153ffb630158e17269cff8ffff935c38ceb1a7", - "blk.9.attn_q.weight": "51b1d0febc3b350945be4504f55afa4347517bde0f710e1a4b88e6b17e71e7c7", - "blk.9.attn_v.weight": "aab7e1db0a8b50a03036356791ffce736ab010d15674c96eaef8049d80076054", - "blk.9.ffn_down.weight": "cbf43ec84becb40c9359a181ab0e641fd7faae7d34b549501f7cfb7afdc3d764", - "blk.9.ffn_gate.weight": "dce0e8661c778327bed7f03b6790d26710764188aed9dc746e6e05863891fa57", - "blk.9.ffn_norm.weight": "6d41642104f995c77bf31122b13237caebda3e7fcccb1367ce91db36b015e923", - "blk.9.ffn_up.weight": "82fe4c67bf24e7b2d6f6e05f7b1234c2bf90c3932951091a9066211b8e15ecbb", - "blk.10.attn_k.weight": "f6a9ed8fd8d3229b5d03175c413ffc56a07f2ce7236271986361dd3d8993f9aa", - "blk.10.attn_norm.weight": "cebbef89f0326ca8e02df3867a571e4d61c20c2a12f295f98ae590d62bc86010", - "blk.10.attn_output.weight": "34f5efb86accb4f06347d83a32558ea8eab3039d128969161a741ebacbb656ff", - "blk.10.attn_q.weight": "1e0efe27df2d5d50f7157253ba2cfd436d6781c3dc78ca176d0c16a210b5b763", - "blk.10.attn_v.weight": "8f085bf50a2b0f83cd6cdda3c8ef5a9e204a36348ed95871aac725d1f68640cf", - "blk.10.ffn_down.weight": "bf3b3cb4cace435809ac7b4cc933f20853af12f1f272d3dcefe7f19c0f203b8b", - "blk.10.ffn_gate.weight": "d3df7a1413b1c5adf1a1dcda9e5225a15c89874bae53bb6137ad1ea42fca2d34", - "blk.10.ffn_norm.weight": "a1da603b0480471b5ed8e862148cecd5fed918f8304d6933ab0bdb25b8d2fb8f", - "blk.10.ffn_up.weight": "bffbba605922e972dc47dda88a0b4659aa52236c76e5fe861a949e6d9a367492", - "blk.11.attn_k.weight": "9f31c63d66cd32c29b1eb8bb829d0c8525ce2ae936e0eefdaab6335a2d12a3df", - "blk.11.attn_norm.weight": "0bde1a266d8b2e8f202bb7e2e88b19147ca83021901f6d3cae77a4df5548c754", - "blk.11.attn_output.weight": "e10725c7cf746ed4a7e472cf7aea6cb564e5db6a1d5197adc980d650a387ccea", - "blk.11.attn_q.weight": "05ee758a7d065802630f8c65dca424364c1c8825e389aa33f9405c45e8a50cce", - "blk.11.attn_v.weight": "0c3ae7090f11775d24c51120db6e305db6aff706493e7ee123dcab74485ba789", - "blk.11.ffn_down.weight": "7ba40b8e12c09c5fb2006b77a771cb01ce894e88a3b3e1877f927a5b89c91709", - "blk.11.ffn_gate.weight": "db76388a023b98097972d354ba1c6a5e26efdeb1c596b9c28bf2cd8f6596975e", - "blk.11.ffn_norm.weight": "a38c3ae1b89a68ddc7b72c99c5b28be7fe3787c4fad9904d0c43d64eaf00c474", - "blk.11.ffn_up.weight": "13c8142f9cf1eddc658babf978daf3515c4ccc45f849f3e7e3930aa18a8480a0", - "blk.12.attn_k.weight": "f03241c36ac87cb57429a2ef22186b8d7d0b590a8b173beb01fa13d93772f3b1", - "blk.12.attn_norm.weight": "4568f654e6d65104d586e7c16ba960c83428698ce103022b7e0be15e2884e13b", - "blk.12.attn_output.weight": "04867603f82f91e41306e09b33ecda0104b3ee4834061f2c0bbdc8da33c72509", - "blk.12.attn_q.weight": "70fe04b9a8e08b6100cc8d6b58bf4cbbad15ca1de82d63baca5d352ba6c4cbae", - "blk.12.attn_v.weight": "15cb28db61a86c98687991d7e611bc92a1fcc6007f3432149cfb5fe518a4f65e", - "blk.12.ffn_down.weight": "6d10c790a4e3dc44c2dc36d96251ae97cdf30a4fa04d4c43e31bfbd038e6a7b7", - "blk.12.ffn_gate.weight": "3462a2d8f6b4743b25e24da51b90018ac2858d05ac7e582bcb69063cfdac1104", - "blk.12.ffn_norm.weight": "1f96392c1faa34e34ae5dea55a6a86c5aa4c79758952075d53d28de89dd88456", - "blk.12.ffn_up.weight": "d22eacc612a7411953d948483c5fb201e11722955ee0754da866e7bec578ac6d", - "blk.13.attn_k.weight": "5864977e6b733ea942647d6feed5c76156c48c200649c22e4e11b9e5860e57f3", - "blk.13.attn_norm.weight": "87e053535144723db4145aa5402acc54331b7696752d852bb9fc542ff33f0fb5", - "blk.13.attn_output.weight": "078145f5ad83f8b14f97a869346f7fd1583b24d1e3edadaa95d3da4242973f8f", - "blk.13.attn_q.weight": "3b8caf35504cbc4d1a7dd6e011a95760703b7f71e2218b030b1254f811362dd7", - "blk.13.attn_v.weight": "4fdf8365a603e043e5b40c4a21c84ac167f9be62794178f9d8a608dfe5653bf9", - "blk.13.ffn_down.weight": "a07d3abbfcacf48ba028df2cab895be32cc15022d23389a745286e79c1b1d1fd", - "blk.13.ffn_gate.weight": "1d2ab39666aa2909acc96787432a3ed13b19d25170f74665fadff9b17bbaffb1", - "blk.13.ffn_norm.weight": "4f2e809fda5f3eadf52578ee50e0ba36e53be91e55dce418c12dfe595f5f18e7", - "blk.13.ffn_up.weight": "8783d2720c2c37ca176a5801e0b3ef1f9cc9cf3ef1cd37af423aaf6b2a27e2bd", - "blk.14.attn_k.weight": "ce9428e2b55d43ae0c6690dbd56182f99adc427694ba8236b405cc8ea5035e86", - "blk.14.attn_norm.weight": "6abb35f9db8251d6ae954bda147c6ada2371b0574d11702e828f3c6ac99b7cc0", - "blk.14.attn_output.weight": "fe3880916d0ceb5bff672c88bbefb7060a545be609bf049beb2024b38221836d", - "blk.14.attn_q.weight": "7c8ad81be6f4a350931fd108b5f7c9e366e8c26ef62d1d85ffef5dca8fd893f8", - "blk.14.attn_v.weight": "e4bdedffacbebe38567a0734dfd67db90e911d9a9669fcde9a7c4ad8a0066c52", - "blk.14.ffn_down.weight": "ef6694dff1e05820aac0cd2b22f39ac7788b4967afc9250775575554c66aab2c", - "blk.14.ffn_gate.weight": "db63c4179e2db704bc505e2b4696e055b593e295a1b7c4c586fc793bdd5aab19", - "blk.14.ffn_norm.weight": "2796a62d832a9710148f95d533320492a33e712b2e5218659c548705bd11684d", - "blk.14.ffn_up.weight": "3f78c78d8c2d54df45f799d4ff902316628af296834afe4ceed63d4a324ff03e", - "blk.15.attn_k.weight": "6e810ee3859e07695645ee0c9a5efc7962668984a5f0a9325f47e462743b447c", - "blk.15.attn_norm.weight": "0956b576ae96db0b28cb09f761f801cfd9281432284664f0fe181c8d9c55d1ec", - "blk.15.attn_output.weight": "03a17f7e94208177aace5cc41b7f54670ba57873b7274ff6e23caf58cce110ca", - "blk.15.attn_q.weight": "b8edafe7d2216a6f8b4ae4905a906475490e6ea418f6e1d3cec563dbdc6fab91", - "blk.15.attn_v.weight": "f8ae8cae0f4cfa34a459824eba57350c3c248104ba5607e7d9dc7d7c39aaf4a6", - "blk.15.ffn_down.weight": "8d02eb439da852246d2ca67e9b7b6de0b090b80744355e64728a23e41926505b", - "blk.15.ffn_gate.weight": "ed5bf361c67db8731f186b775826f21c33bdb521111fd2d922539719a770239f", - "blk.15.ffn_norm.weight": "5942ca3c73209ac9a0c8bfd9b4aab7f7be7aee9aa12d9c35833493b44af76767", - "blk.15.ffn_up.weight": "f4bebf4ad99ec5f911327dec347be6c595814885309c7bc5647ce28c7f4d1cf5", - "blk.16.attn_k.weight": "756a534c19364448e0958b8948fe33891c6ccda0fbb4dfa2024e1f532a87804b", - "blk.16.attn_norm.weight": "386b7b9e4e6509f6af9c022d942b6c6c6cc136aeed8751ecb037c74d7c4bfb93", - "blk.16.attn_output.weight": "3ba1a766a25830b84d7c22178203635f9c5624caad290bc5e5d73da5d5e7a2ec", - "blk.16.attn_q.weight": "d39b0c91e1fda7685d50a0f7cc8d18c44b5bdc90a142c7fda0bc329cca1afa74", - "blk.16.attn_v.weight": "98b33fcb0ee3483cff1b06ecb44d7b7ffb4d34c268248e4d73dfdf82b2065b2f", - "blk.16.ffn_down.weight": "14006f5e4acb2f9416271ae562e299359cd2585739c7fc77ccbca54495563948", - "blk.16.ffn_gate.weight": "12f8abae2d301d8f88bedb6af98b1daecc7b0b8d05148594f931f30958d77aca", - "blk.16.ffn_norm.weight": "129a15a046ee96d06de288bd43c80f77a6b0fb3a159c7367154c6e4aaf362672", - "blk.16.ffn_up.weight": "b4a5911a45f3871ef1d4efb7dc7108645a564b70f818eccf45beebef2e844ee9", - "blk.17.attn_k.weight": "5e1bfcff0146ebdde3817b656952892eb671e14e75afc92fa53f84f8eecbec4c", - "blk.17.attn_norm.weight": "60bc988fab7c4b29ee9de599df41a8de00caa94fcd74677da011fac82f60f465", - "blk.17.attn_output.weight": "ba49b40d6a0b5685f749c24b0edbed3adc44dbe13b5d5e5fa1e56169fc746555", - "blk.17.attn_q.weight": "82bb415d24efcd14d03ace03f907bb70db6a204c76a0bdd1892e0fba165db87d", - "blk.17.attn_v.weight": "73dbe54beb91a899884e275ea81ffc5187a20cb7d5b68d5c299b783096999d94", - "blk.17.ffn_down.weight": "7c086166241e0664f8963fd1ca4ed74c737abfb2525ec20f8435821ff50158f3", - "blk.17.ffn_gate.weight": "51a32f78244d42a539f619c5ce661db9e6cf41636280a826d439b5444edcd28c", - "blk.17.ffn_norm.weight": "c4bb247fccd1ecc84875028af63dd20aaf5cbd17eb94a9bc36679c09285dccab", - "blk.17.ffn_up.weight": "b5886182790bc6fbadd63de9bc4ffee416f3b69a66280d197ab8c18edf769abf", - "output_norm.weight": "481f3097d0a20412e35b3a739b1b958487bcd41ff67744baa3c9acbddd2ee4d4" -} diff --git a/ollama/convert/tokenizer.go b/ollama/convert/tokenizer.go deleted file mode 100755 index 0d42a6d..0000000 --- a/ollama/convert/tokenizer.go +++ /dev/null @@ -1,265 +0,0 @@ -package convert - -import ( - "cmp" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "io/fs" - "log/slog" - "os" - "slices" -) - -const ( - _ int32 = iota - tokenTypeNormal - tokenTypeUnknown - tokenTypeControl - tokenTypeUserDefined - tokenTypeUnused - tokenTypeByte -) - -type Tokenizer struct { - *Vocabulary - SpecialVocabulary []*SpecialVocabulary - Merges []string - - Pre string - Template string -} - -func parseTokenizer(fsys fs.FS, specialTokenTypes []string) (*Tokenizer, error) { - v, err := parseVocabulary(fsys) - if err != nil { - return nil, err - } - - t := &Tokenizer{ - Vocabulary: v, - Pre: "default", - } - - addedTokens := make(map[string]token) - if f, err := fsys.Open("tokenizer.json"); errors.Is(err, os.ErrNotExist) { - } else if err != nil { - return nil, err - } else { - defer f.Close() - - var tt tokenizer - if err := json.NewDecoder(f).Decode(&tt); err != nil { - return nil, err - } - - for _, t := range tt.AddedTokens { - addedTokens[t.Content] = t - } - - t.Merges = tt.Model.Merges - - sha256sum := sha256.New() - for _, pt := range tt.PreTokenizer.PreTokenizers { - switch pt.Type { - case "Split": - if pt.Pattern.Regex != "" { - // create a checksum of all Split pretokenizers which should be sufficient - // to identify the pretokenizer - sha256sum.Write([]byte(pt.Pattern.Regex)) - } - } - } - - switch digest := hex.EncodeToString(sha256sum.Sum(nil)); digest { - case "d98f9631be1e9607a9848c26c1f9eac1aa9fc21ac6ba82a2fc0741af9780a48f": - t.Pre = "llama-bpe" - case "03df5c5863ad70781dcfdef491ead25140f895fe8010964be0daefe27be32b02": - t.Pre = "deepseek-llm" - case "21cde974d587f0d54dc8d56b183cc1e6239600172035c68fbd6d4b9f8da0576e": - t.Pre = "deepseek-coder" - case "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855": - // noop, empty pretokenizer - default: - slog.Warn("unknown pretokenizer, using default", "digest", digest) - } - } - - if f, err := fsys.Open("tokenizer_config.json"); errors.Is(err, os.ErrNotExist) { - } else if err != nil { - return nil, err - } else { - defer f.Close() - - var p map[string]json.RawMessage - if err := json.NewDecoder(f).Decode(&p); err != nil { - return nil, err - } - - if template, ok := p["chat_template"]; ok { - if err := json.Unmarshal(template, &t.Template); err != nil { - return nil, err - } - } - - for _, st := range specialTokenTypes { - sv := SpecialVocabulary{Type: st} - if bts, ok := p[fmt.Sprintf("add_%s_token", st)]; ok { - if err := json.Unmarshal(bts, &sv.AddToken); err != nil { - return nil, err - } - } - - if bts, ok := p[fmt.Sprintf("%s_token", st)]; ok { - var content string - if err := json.Unmarshal(bts, &content); err != nil { - var mm map[string]any - if err := json.Unmarshal(bts, &mm); err != nil { - continue - } - - content, ok = mm["content"].(string) - if !ok { - continue - } - } - - sv.Content = content - } - - if id, ok := addedTokens[sv.Content]; ok { - sv.ID = id.ID - t.SpecialVocabulary = append(t.SpecialVocabulary, &sv) - } - } - } - - return t, nil -} - -type tokenizer struct { - Version string `json:"version"` - AddedTokens []token `json:"added_tokens"` - Model struct { - Type string `json:"type"` - Vocab map[string]int `json:"vocab"` - Merges []string `json:"merges"` - } `json:"model"` - - PreTokenizer struct { - PreTokenizers []struct { - Type string `json:"type"` - Pattern struct { - Regex string `json:"Regex"` - } `json:"pattern"` - } `json:"pretokenizers"` - } `json:"pre_tokenizer"` -} - -type token struct { - ID int `json:"id"` - Content string `json:"content"` - Special bool `json:"special"` - UserDefined bool -} - -type Vocabulary struct { - Model string - Tokens []string - Scores []float32 - Types []int32 -} - -func parseVocabularyFromTokenizer(fsys fs.FS) (*Vocabulary, error) { - f, err := fsys.Open("tokenizer.json") - if err != nil { - return nil, err - } - defer f.Close() - - var t tokenizer - if err := json.NewDecoder(f).Decode(&t); err != nil { - return nil, err - } - - var tokens []token - for k, v := range t.Model.Vocab { - tokens = append(tokens, token{ - ID: v, - Content: k, - }) - } - - for _, t := range t.AddedTokens { - t.UserDefined = true - tokens = append(tokens, t) - } - - slices.SortFunc(tokens, func(i, j token) int { - return cmp.Compare(i.ID, j.ID) - }) - - v := Vocabulary{Model: "gpt2"} - for _, t := range tokens { - v.Tokens = append(v.Tokens, t.Content) - v.Scores = append(v.Scores, float32(t.ID)) - - switch { - case t.Special: - v.Types = append(v.Types, tokenTypeControl) - case t.UserDefined: - v.Types = append(v.Types, tokenTypeUserDefined) - default: - v.Types = append(v.Types, tokenTypeNormal) - } - } - - return &v, nil -} - -func parseVocabulary(fsys fs.FS) (*Vocabulary, error) { - patterns := []struct { - Pattern string - Func func(fs.FS) (*Vocabulary, error) - }{ - {"tokenizer.model", parseSentencePiece}, - {"tokenizer.json", parseVocabularyFromTokenizer}, - } - - for _, pattern := range patterns { - if _, err := fs.Stat(fsys, pattern.Pattern); errors.Is(err, os.ErrNotExist) { - continue - } else if err != nil { - return nil, err - } - - return pattern.Func(fsys) - } - - return nil, errors.New("unknown tensor format") -} - -type SpecialVocabulary struct { - Type string - ID int - Content string - AddToken bool -} - -func (sv SpecialVocabulary) Key() string { - switch t := sv.Type; t { - case "bos", "eos", "cls", "mask": - return t - case "unk": - return "unknown" - case "sep": - //nolint:misspell // this is an upstream typo - return "seperator" - case "pad": - return "padding" - } - - panic("unknown special vocabulary type") -} diff --git a/ollama/convert/tokenizer_spm.go b/ollama/convert/tokenizer_spm.go deleted file mode 100755 index babf702..0000000 --- a/ollama/convert/tokenizer_spm.go +++ /dev/null @@ -1,83 +0,0 @@ -package convert - -import ( - "cmp" - "encoding/json" - "errors" - "fmt" - "io/fs" - "os" - "slices" - - "google.golang.org/protobuf/proto" - - "github.com/ollama/ollama/convert/sentencepiece" -) - -func parseSentencePiece(fsys fs.FS) (*Vocabulary, error) { - bts, err := fs.ReadFile(fsys, "tokenizer.model") - if err != nil { - return nil, err - } - - var spm sentencepiece.ModelProto - if err := proto.Unmarshal(bts, &spm); err != nil { - return nil, err - } - - v := Vocabulary{Model: "llama"} - for _, piece := range spm.GetPieces() { - v.Tokens = append(v.Tokens, piece.GetPiece()) - v.Scores = append(v.Scores, piece.GetScore()) - - switch t := piece.GetType(); t { - case sentencepiece.ModelProto_SentencePiece_UNKNOWN, - sentencepiece.ModelProto_SentencePiece_CONTROL, - sentencepiece.ModelProto_SentencePiece_UNUSED, - sentencepiece.ModelProto_SentencePiece_BYTE: - v.Types = append(v.Types, int32(t)) - default: - v.Types = append(v.Types, int32(sentencepiece.ModelProto_SentencePiece_NORMAL)) - } - } - - f, err := fsys.Open("added_tokens.json") - if errors.Is(err, os.ErrNotExist) { - return &v, nil - } else if err != nil { - return nil, err - } - defer f.Close() - - var atm map[string]int - if err := json.NewDecoder(f).Decode(&atm); err != nil { - return nil, err - } - - type t struct { - id int - content string - } - - var ts []t - for content, id := range atm { - ts = append(ts, t{id, content}) - } - - slices.SortFunc(ts, func(i, j t) int { - return cmp.Compare(i.id, j.id) - }) - - n := len(v.Tokens) - for i, t := range ts { - if t.id != i+n { - return nil, fmt.Errorf("invalid token id: %d", t.id) - } - - v.Tokens = append(v.Tokens, t.content) - v.Scores = append(v.Scores, -1000.0) - v.Types = append(v.Types, tokenTypeUserDefined) - } - - return &v, nil -} diff --git a/ollama/docs/README.md b/ollama/docs/README.md deleted file mode 100755 index b622104..0000000 --- a/ollama/docs/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Documentation - -### Getting Started -* [Quickstart](../README.md#quickstart) -* [Examples](../examples) -* [Importing models](./import.md) -* [Linux Documentation](./linux.md) -* [Windows Documentation](./windows.md) -* [Docker Documentation](./docker.md) - -### Reference - -* [API Reference](./api.md) -* [Modelfile Reference](./modelfile.md) -* [OpenAI Compatibility](./openai.md) - -### Resources - -* [Troubleshooting Guide](./troubleshooting.md) -* [FAQ](./faq.md) -* [Development guide](./development.md) diff --git a/ollama/docs/api.md b/ollama/docs/api.md deleted file mode 100755 index aed2b69..0000000 --- a/ollama/docs/api.md +++ /dev/null @@ -1,1293 +0,0 @@ -# API - -## Endpoints - -- [Generate a completion](#generate-a-completion) -- [Generate a chat completion](#generate-a-chat-completion) -- [Create a Model](#create-a-model) -- [List Local Models](#list-local-models) -- [Show Model Information](#show-model-information) -- [Copy a Model](#copy-a-model) -- [Delete a Model](#delete-a-model) -- [Pull a Model](#pull-a-model) -- [Push a Model](#push-a-model) -- [Generate Embeddings](#generate-embeddings) -- [List Running Models](#list-running-models) - -## Conventions - -### Model names - -Model names follow a `model:tag` format, where `model` can have an optional namespace such as `example/model`. Some examples are `orca-mini:3b-q4_1` and `llama3:70b`. The tag is optional and, if not provided, will default to `latest`. The tag is used to identify a specific version. - -### Durations - -All durations are returned in nanoseconds. - -### Streaming responses - -Certain endpoints stream responses as JSON objects. Streaming can be disabled by providing `{"stream": false}` for these endpoints. - -## Generate a completion - -```shell -POST /api/generate -``` - -Generate a response for a given prompt with a provided model. This is a streaming endpoint, so there will be a series of responses. The final response object will include statistics and additional data from the request. - -### Parameters - -- `model`: (required) the [model name](#model-names) -- `prompt`: the prompt to generate a response for -- `suffix`: the text after the model response -- `images`: (optional) a list of base64-encoded images (for multimodal models such as `llava`) - -Advanced parameters (optional): - -- `format`: the format to return a response in. Currently the only accepted value is `json` -- `options`: additional model parameters listed in the documentation for the [Modelfile](./modelfile.md#valid-parameters-and-values) such as `temperature` -- `system`: system message to (overrides what is defined in the `Modelfile`) -- `template`: the prompt template to use (overrides what is defined in the `Modelfile`) -- `context`: the context parameter returned from a previous request to `/generate`, this can be used to keep a short conversational memory -- `stream`: if `false` the response will be returned as a single response object, rather than a stream of objects -- `raw`: if `true` no formatting will be applied to the prompt. You may choose to use the `raw` parameter if you are specifying a full templated prompt in your request to the API -- `keep_alive`: controls how long the model will stay loaded into memory following the request (default: `5m`) - -#### JSON mode - -Enable JSON mode by setting the `format` parameter to `json`. This will structure the response as a valid JSON object. See the JSON mode [example](#request-json-mode) below. - -> [!IMPORTANT] -> It's important to instruct the model to use JSON in the `prompt`. Otherwise, the model may generate large amounts whitespace. - -### Examples - -#### Generate request (Streaming) - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3", - "prompt": "Why is the sky blue?" -}' -``` - -##### Response - -A stream of JSON objects is returned: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T08:52:19.385406455-07:00", - "response": "The", - "done": false -} -``` - -The final response in the stream also includes additional data about the generation: - -- `total_duration`: time spent generating the response -- `load_duration`: time spent in nanoseconds loading the model -- `prompt_eval_count`: number of tokens in the prompt -- `prompt_eval_duration`: time spent in nanoseconds evaluating the prompt -- `eval_count`: number of tokens in the response -- `eval_duration`: time in nanoseconds spent generating the response -- `context`: an encoding of the conversation used in this response, this can be sent in the next request to keep a conversational memory -- `response`: empty if the response was streamed, if not streamed, this will contain the full response - -To calculate how fast the response is generated in tokens per second (token/s), divide `eval_count` / `eval_duration` * `10^9`. - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T19:22:45.499127Z", - "response": "", - "done": true, - "context": [1, 2, 3], - "total_duration": 10706818083, - "load_duration": 6338219291, - "prompt_eval_count": 26, - "prompt_eval_duration": 130079000, - "eval_count": 259, - "eval_duration": 4232710000 -} -``` - -#### Request (No streaming) - -##### Request - -A response can be received in one reply when streaming is off. - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3", - "prompt": "Why is the sky blue?", - "stream": false -}' -``` - -##### Response - -If `stream` is set to `false`, the response will be a single JSON object: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T19:22:45.499127Z", - "response": "The sky is blue because it is the color of the sky.", - "done": true, - "context": [1, 2, 3], - "total_duration": 5043500667, - "load_duration": 5025959, - "prompt_eval_count": 26, - "prompt_eval_duration": 325953000, - "eval_count": 290, - "eval_duration": 4709213000 -} -``` - -#### Request (with suffix) - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "codellama:code", - "prompt": "def compute_gcd(a, b):", - "suffix": " return result", - "options": { - "temperature": 0 - }, - "stream": false -}' -``` - -##### Response - -```json -{ - "model": "codellama:code", - "created_at": "2024-07-22T20:47:51.147561Z", - "response": "\n if a == 0:\n return b\n else:\n return compute_gcd(b % a, a)\n\ndef compute_lcm(a, b):\n result = (a * b) / compute_gcd(a, b)\n", - "done": true, - "done_reason": "stop", - "context": [...], - "total_duration": 1162761250, - "load_duration": 6683708, - "prompt_eval_count": 17, - "prompt_eval_duration": 201222000, - "eval_count": 63, - "eval_duration": 953997000 -} -``` - -#### Request (JSON mode) - -> [!IMPORTANT] -> When `format` is set to `json`, the output will always be a well-formed JSON object. It's important to also instruct the model to respond in JSON. - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3", - "prompt": "What color is the sky at different times of the day? Respond using JSON", - "format": "json", - "stream": false -}' -``` - -##### Response - -```json -{ - "model": "llama3", - "created_at": "2023-11-09T21:07:55.186497Z", - "response": "{\n\"morning\": {\n\"color\": \"blue\"\n},\n\"noon\": {\n\"color\": \"blue-gray\"\n},\n\"afternoon\": {\n\"color\": \"warm gray\"\n},\n\"evening\": {\n\"color\": \"orange\"\n}\n}\n", - "done": true, - "context": [1, 2, 3], - "total_duration": 4648158584, - "load_duration": 4071084, - "prompt_eval_count": 36, - "prompt_eval_duration": 439038000, - "eval_count": 180, - "eval_duration": 4196918000 -} -``` - -The value of `response` will be a string containing JSON similar to: - -```json -{ - "morning": { - "color": "blue" - }, - "noon": { - "color": "blue-gray" - }, - "afternoon": { - "color": "warm gray" - }, - "evening": { - "color": "orange" - } -} -``` - -#### Request (with images) - -To submit images to multimodal models such as `llava` or `bakllava`, provide a list of base64-encoded `images`: - -#### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llava", - "prompt":"What is in this picture?", - "stream": false, - "images": ["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"] -}' -``` - -#### Response - -``` -{ - "model": "llava", - "created_at": "2023-11-03T15:36:02.583064Z", - "response": "A happy cartoon character, which is cute and cheerful.", - "done": true, - "context": [1, 2, 3], - "total_duration": 2938432250, - "load_duration": 2559292, - "prompt_eval_count": 1, - "prompt_eval_duration": 2195557000, - "eval_count": 44, - "eval_duration": 736432000 -} -``` - -#### Request (Raw Mode) - -In some cases, you may wish to bypass the templating system and provide a full prompt. In this case, you can use the `raw` parameter to disable templating. Also note that raw mode will not return a context. - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "mistral", - "prompt": "[INST] why is the sky blue? [/INST]", - "raw": true, - "stream": false -}' -``` - -#### Request (Reproducible outputs) - -For reproducible outputs, set `seed` to a number: - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "mistral", - "prompt": "Why is the sky blue?", - "options": { - "seed": 123 - } -}' -``` - -##### Response - -```json -{ - "model": "mistral", - "created_at": "2023-11-03T15:36:02.583064Z", - "response": " The sky appears blue because of a phenomenon called Rayleigh scattering.", - "done": true, - "total_duration": 8493852375, - "load_duration": 6589624375, - "prompt_eval_count": 14, - "prompt_eval_duration": 119039000, - "eval_count": 110, - "eval_duration": 1779061000 -} -``` - -#### Generate request (With options) - -If you want to set custom options for the model at runtime rather than in the Modelfile, you can do so with the `options` parameter. This example sets every available option, but you can set any of them individually and omit the ones you do not want to override. - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3", - "prompt": "Why is the sky blue?", - "stream": false, - "options": { - "num_keep": 5, - "seed": 42, - "num_predict": 100, - "top_k": 20, - "top_p": 0.9, - "min_p": 0.0, - "tfs_z": 0.5, - "typical_p": 0.7, - "repeat_last_n": 33, - "temperature": 0.8, - "repeat_penalty": 1.2, - "presence_penalty": 1.5, - "frequency_penalty": 1.0, - "mirostat": 1, - "mirostat_tau": 0.8, - "mirostat_eta": 0.6, - "penalize_newline": true, - "stop": ["\n", "user:"], - "numa": false, - "num_ctx": 1024, - "num_batch": 2, - "num_gpu": 1, - "main_gpu": 0, - "low_vram": false, - "f16_kv": true, - "vocab_only": false, - "use_mmap": true, - "use_mlock": false, - "num_thread": 8 - } -}' -``` - -##### Response - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T19:22:45.499127Z", - "response": "The sky is blue because it is the color of the sky.", - "done": true, - "context": [1, 2, 3], - "total_duration": 4935886791, - "load_duration": 534986708, - "prompt_eval_count": 26, - "prompt_eval_duration": 107345000, - "eval_count": 237, - "eval_duration": 4289432000 -} -``` - -#### Load a model - -If an empty prompt is provided, the model will be loaded into memory. - -##### Request - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3" -}' -``` - -##### Response - -A single JSON object is returned: - -```json -{ - "model": "llama3", - "created_at": "2023-12-18T19:52:07.071755Z", - "response": "", - "done": true -} -``` - -## Generate a chat completion - -```shell -POST /api/chat -``` - -Generate the next message in a chat with a provided model. This is a streaming endpoint, so there will be a series of responses. Streaming can be disabled using `"stream": false`. The final response object will include statistics and additional data from the request. - -### Parameters - -- `model`: (required) the [model name](#model-names) -- `messages`: the messages of the chat, this can be used to keep a chat memory -- `tools`: tools for the model to use if supported. Requires `stream` to be set to `false` - -The `message` object has the following fields: - -- `role`: the role of the message, either `system`, `user`, `assistant`, or `tool` -- `content`: the content of the message -- `images` (optional): a list of images to include in the message (for multimodal models such as `llava`) -- `tool_calls` (optional): a list of tools the model wants to use - -Advanced parameters (optional): - -- `format`: the format to return a response in. Currently the only accepted value is `json` -- `options`: additional model parameters listed in the documentation for the [Modelfile](./modelfile.md#valid-parameters-and-values) such as `temperature` -- `stream`: if `false` the response will be returned as a single response object, rather than a stream of objects -- `keep_alive`: controls how long the model will stay loaded into memory following the request (default: `5m`) - -### Examples - -#### Chat Request (Streaming) - -##### Request - -Send a chat message with a streaming response. - -```shell -curl http://localhost:11434/api/chat -d '{ - "model": "llama3", - "messages": [ - { - "role": "user", - "content": "why is the sky blue?" - } - ] -}' -``` - -##### Response - -A stream of JSON objects is returned: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T08:52:19.385406455-07:00", - "message": { - "role": "assistant", - "content": "The", - "images": null - }, - "done": false -} -``` - -Final response: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T19:22:45.499127Z", - "done": true, - "total_duration": 4883583458, - "load_duration": 1334875, - "prompt_eval_count": 26, - "prompt_eval_duration": 342546000, - "eval_count": 282, - "eval_duration": 4535599000 -} -``` - -#### Chat request (No streaming) - -##### Request - -```shell -curl http://localhost:11434/api/chat -d '{ - "model": "llama3", - "messages": [ - { - "role": "user", - "content": "why is the sky blue?" - } - ], - "stream": false -}' -``` - -##### Response - -```json -{ - "model": "registry.ollama.ai/library/llama3:latest", - "created_at": "2023-12-12T14:13:43.416799Z", - "message": { - "role": "assistant", - "content": "Hello! How are you today?" - }, - "done": true, - "total_duration": 5191566416, - "load_duration": 2154458, - "prompt_eval_count": 26, - "prompt_eval_duration": 383809000, - "eval_count": 298, - "eval_duration": 4799921000 -} -``` - -#### Chat request (With History) - -Send a chat message with a conversation history. You can use this same approach to start the conversation using multi-shot or chain-of-thought prompting. - -##### Request - -```shell -curl http://localhost:11434/api/chat -d '{ - "model": "llama3", - "messages": [ - { - "role": "user", - "content": "why is the sky blue?" - }, - { - "role": "assistant", - "content": "due to rayleigh scattering." - }, - { - "role": "user", - "content": "how is that different than mie scattering?" - } - ] -}' -``` - -##### Response - -A stream of JSON objects is returned: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T08:52:19.385406455-07:00", - "message": { - "role": "assistant", - "content": "The" - }, - "done": false -} -``` - -Final response: - -```json -{ - "model": "llama3", - "created_at": "2023-08-04T19:22:45.499127Z", - "done": true, - "total_duration": 8113331500, - "load_duration": 6396458, - "prompt_eval_count": 61, - "prompt_eval_duration": 398801000, - "eval_count": 468, - "eval_duration": 7701267000 -} -``` - -#### Chat request (with images) - -##### Request - -Send a chat message with images. The images should be provided as an array, with the individual images encoded in Base64. - -```shell -curl http://localhost:11434/api/chat -d '{ - "model": "llava", - "messages": [ - { - "role": "user", - "content": "what is in this image?", - "images": ["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"] - } - ] -}' -``` - -##### Response - -```json -{ - "model": "llava", - "created_at": "2023-12-13T22:42:50.203334Z", - "message": { - "role": "assistant", - "content": " The image features a cute, little pig with an angry facial expression. It's wearing a heart on its shirt and is waving in the air. This scene appears to be part of a drawing or sketching project.", - "images": null - }, - "done": true, - "total_duration": 1668506709, - "load_duration": 1986209, - "prompt_eval_count": 26, - "prompt_eval_duration": 359682000, - "eval_count": 83, - "eval_duration": 1303285000 -} -``` - -#### Chat request (Reproducible outputs) - -##### Request - -```shell -curl http://localhost:11434/api/chat -d '{ - "model": "llama3", - "messages": [ - { - "role": "user", - "content": "Hello!" - } - ], - "options": { - "seed": 101, - "temperature": 0 - } -}' -``` - -##### Response - -```json -{ - "model": "registry.ollama.ai/library/llama3:latest", - "created_at": "2023-12-12T14:13:43.416799Z", - "message": { - "role": "assistant", - "content": "Hello! How are you today?" - }, - "done": true, - "total_duration": 5191566416, - "load_duration": 2154458, - "prompt_eval_count": 26, - "prompt_eval_duration": 383809000, - "eval_count": 298, - "eval_duration": 4799921000 -} -``` - -#### Chat request (with tools) - -##### Request - -``` -curl http://localhost:11434/api/chat -d '{ - "model": "llama3.1", - "messages": [ - { - "role": "user", - "content": "What is the weather today in Paris?" - } - ], - "stream": false, - "tools": [ - { - "type": "function", - "function": { - "name": "get_current_weather", - "description": "Get the current weather for a location", - "parameters": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The location to get the weather for, e.g. San Francisco, CA" - }, - "format": { - "type": "string", - "description": "The format to return the weather in, e.g. 'celsius' or 'fahrenheit'", - "enum": ["celsius", "fahrenheit"] - } - }, - "required": ["location", "format"] - } - } - } - ] -}' -``` - -##### Response - -```json -{ - "model": "llama3.1", - "created_at": "2024-07-22T20:33:28.123648Z", - "message": { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "function": { - "name": "get_current_weather", - "arguments": { - "format": "celsius", - "location": "Paris, FR" - } - } - } - ] - }, - "done_reason": "stop", - "done": true, - "total_duration": 885095291, - "load_duration": 3753500, - "prompt_eval_count": 122, - "prompt_eval_duration": 328493000, - "eval_count": 33, - "eval_duration": 552222000 -} -``` - -## Create a Model - -```shell -POST /api/create -``` - -Create a model from a [`Modelfile`](./modelfile.md). It is recommended to set `modelfile` to the content of the Modelfile rather than just set `path`. This is a requirement for remote create. Remote model creation must also create any file blobs, fields such as `FROM` and `ADAPTER`, explicitly with the server using [Create a Blob](#create-a-blob) and the value to the path indicated in the response. - -### Parameters - -- `name`: name of the model to create -- `modelfile` (optional): contents of the Modelfile -- `stream`: (optional) if `false` the response will be returned as a single response object, rather than a stream of objects -- `path` (optional): path to the Modelfile - -### Examples - -#### Create a new model - -Create a new model from a `Modelfile`. - -##### Request - -```shell -curl http://localhost:11434/api/create -d '{ - "name": "mario", - "modelfile": "FROM llama3\nSYSTEM You are mario from Super Mario Bros." -}' -``` - -##### Response - -A stream of JSON objects. Notice that the final JSON object shows a `"status": "success"`. - -```json -{"status":"reading model metadata"} -{"status":"creating system layer"} -{"status":"using already created layer sha256:22f7f8ef5f4c791c1b03d7eb414399294764d7cc82c7e94aa81a1feb80a983a2"} -{"status":"using already created layer sha256:8c17c2ebb0ea011be9981cc3922db8ca8fa61e828c5d3f44cb6ae342bf80460b"} -{"status":"using already created layer sha256:7c23fb36d80141c4ab8cdbb61ee4790102ebd2bf7aeff414453177d4f2110e5d"} -{"status":"using already created layer sha256:2e0493f67d0c8c9c68a8aeacdf6a38a2151cb3c4c1d42accf296e19810527988"} -{"status":"using already created layer sha256:2759286baa875dc22de5394b4a925701b1896a7e3f8e53275c36f75a877a82c9"} -{"status":"writing layer sha256:df30045fe90f0d750db82a058109cecd6d4de9c90a3d75b19c09e5f64580bb42"} -{"status":"writing layer sha256:f18a68eb09bf925bb1b669490407c1b1251c5db98dc4d3d81f3088498ea55690"} -{"status":"writing manifest"} -{"status":"success"} -``` - -### Check if a Blob Exists - -```shell -HEAD /api/blobs/:digest -``` - -Ensures that the file blob used for a FROM or ADAPTER field exists on the server. This is checking your Ollama server and not Ollama.ai. - -#### Query Parameters - -- `digest`: the SHA256 digest of the blob - -#### Examples - -##### Request - -```shell -curl -I http://localhost:11434/api/blobs/sha256:29fdb92e57cf0827ded04ae6461b5931d01fa595843f55d36f5b275a52087dd2 -``` - -##### Response - -Return 200 OK if the blob exists, 404 Not Found if it does not. - -### Create a Blob - -```shell -POST /api/blobs/:digest -``` - -Create a blob from a file on the server. Returns the server file path. - -#### Query Parameters - -- `digest`: the expected SHA256 digest of the file - -#### Examples - -##### Request - -```shell -curl -T model.bin -X POST http://localhost:11434/api/blobs/sha256:29fdb92e57cf0827ded04ae6461b5931d01fa595843f55d36f5b275a52087dd2 -``` - -##### Response - -Return 201 Created if the blob was successfully created, 400 Bad Request if the digest used is not expected. - -## List Local Models - -```shell -GET /api/tags -``` - -List models that are available locally. - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/tags -``` - -#### Response - -A single JSON object will be returned. - -```json -{ - "models": [ - { - "name": "codellama:13b", - "modified_at": "2023-11-04T14:56:49.277302595-07:00", - "size": 7365960935, - "digest": "9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697", - "details": { - "format": "gguf", - "family": "llama", - "families": null, - "parameter_size": "13B", - "quantization_level": "Q4_0" - } - }, - { - "name": "llama3:latest", - "modified_at": "2023-12-07T09:32:18.757212583-08:00", - "size": 3825819519, - "digest": "fe938a131f40e6f6d40083c9f0f430a515233eb2edaa6d72eb85c50d64f2300e", - "details": { - "format": "gguf", - "family": "llama", - "families": null, - "parameter_size": "7B", - "quantization_level": "Q4_0" - } - } - ] -} -``` - -## Show Model Information - -```shell -POST /api/show -``` - -Show information about a model including details, modelfile, template, parameters, license, system prompt. - -### Parameters - -- `name`: name of the model to show -- `verbose`: (optional) if set to `true`, returns full data for verbose response fields - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/show -d '{ - "name": "llama3" -}' -``` - -#### Response - -```json -{ - "modelfile": "# Modelfile generated by \"ollama show\"\n# To build a new Modelfile based on this one, replace the FROM line with:\n# FROM llava:latest\n\nFROM /Users/matt/.ollama/models/blobs/sha256:200765e1283640ffbd013184bf496e261032fa75b99498a9613be4e94d63ad52\nTEMPLATE \"\"\"{{ .System }}\nUSER: {{ .Prompt }}\nASSISTANT: \"\"\"\nPARAMETER num_ctx 4096\nPARAMETER stop \"\u003c/s\u003e\"\nPARAMETER stop \"USER:\"\nPARAMETER stop \"ASSISTANT:\"", - "parameters": "num_keep 24\nstop \"<|start_header_id|>\"\nstop \"<|end_header_id|>\"\nstop \"<|eot_id|>\"", - "template": "{{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>\n\n{{ .Response }}<|eot_id|>", - "details": { - "parent_model": "", - "format": "gguf", - "family": "llama", - "families": [ - "llama" - ], - "parameter_size": "8.0B", - "quantization_level": "Q4_0" - }, - "model_info": { - "general.architecture": "llama", - "general.file_type": 2, - "general.parameter_count": 8030261248, - "general.quantization_version": 2, - "llama.attention.head_count": 32, - "llama.attention.head_count_kv": 8, - "llama.attention.layer_norm_rms_epsilon": 0.00001, - "llama.block_count": 32, - "llama.context_length": 8192, - "llama.embedding_length": 4096, - "llama.feed_forward_length": 14336, - "llama.rope.dimension_count": 128, - "llama.rope.freq_base": 500000, - "llama.vocab_size": 128256, - "tokenizer.ggml.bos_token_id": 128000, - "tokenizer.ggml.eos_token_id": 128009, - "tokenizer.ggml.merges": [], // populates if `verbose=true` - "tokenizer.ggml.model": "gpt2", - "tokenizer.ggml.pre": "llama-bpe", - "tokenizer.ggml.token_type": [], // populates if `verbose=true` - "tokenizer.ggml.tokens": [] // populates if `verbose=true` - } -} -``` - -## Copy a Model - -```shell -POST /api/copy -``` - -Copy a model. Creates a model with another name from an existing model. - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/copy -d '{ - "source": "llama3", - "destination": "llama3-backup" -}' -``` - -#### Response - -Returns a 200 OK if successful, or a 404 Not Found if the source model doesn't exist. - -## Delete a Model - -```shell -DELETE /api/delete -``` - -Delete a model and its data. - -### Parameters - -- `name`: model name to delete - -### Examples - -#### Request - -```shell -curl -X DELETE http://localhost:11434/api/delete -d '{ - "name": "llama3:13b" -}' -``` - -#### Response - -Returns a 200 OK if successful, 404 Not Found if the model to be deleted doesn't exist. - -## Pull a Model - -```shell -POST /api/pull -``` - -Download a model from the ollama library. Cancelled pulls are resumed from where they left off, and multiple calls will share the same download progress. - -### Parameters - -- `name`: name of the model to pull -- `insecure`: (optional) allow insecure connections to the library. Only use this if you are pulling from your own library during development. -- `stream`: (optional) if `false` the response will be returned as a single response object, rather than a stream of objects - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/pull -d '{ - "name": "llama3" -}' -``` - -#### Response - -If `stream` is not specified, or set to `true`, a stream of JSON objects is returned: - -The first object is the manifest: - -```json -{ - "status": "pulling manifest" -} -``` - -Then there is a series of downloading responses. Until any of the download is completed, the `completed` key may not be included. The number of files to be downloaded depends on the number of layers specified in the manifest. - -```json -{ - "status": "downloading digestname", - "digest": "digestname", - "total": 2142590208, - "completed": 241970 -} -``` - -After all the files are downloaded, the final responses are: - -```json -{ - "status": "verifying sha256 digest" -} -{ - "status": "writing manifest" -} -{ - "status": "removing any unused layers" -} -{ - "status": "success" -} -``` - -if `stream` is set to false, then the response is a single JSON object: - -```json -{ - "status": "success" -} -``` - -## Push a Model - -```shell -POST /api/push -``` - -Upload a model to a model library. Requires registering for ollama.ai and adding a public key first. - -### Parameters - -- `name`: name of the model to push in the form of `/:` -- `insecure`: (optional) allow insecure connections to the library. Only use this if you are pushing to your library during development. -- `stream`: (optional) if `false` the response will be returned as a single response object, rather than a stream of objects - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/push -d '{ - "name": "mattw/pygmalion:latest" -}' -``` - -#### Response - -If `stream` is not specified, or set to `true`, a stream of JSON objects is returned: - -```json -{ "status": "retrieving manifest" } -``` - -and then: - -```json -{ - "status": "starting upload", - "digest": "sha256:bc07c81de745696fdf5afca05e065818a8149fb0c77266fb584d9b2cba3711ab", - "total": 1928429856 -} -``` - -Then there is a series of uploading responses: - -```json -{ - "status": "starting upload", - "digest": "sha256:bc07c81de745696fdf5afca05e065818a8149fb0c77266fb584d9b2cba3711ab", - "total": 1928429856 -} -``` - -Finally, when the upload is complete: - -```json -{"status":"pushing manifest"} -{"status":"success"} -``` - -If `stream` is set to `false`, then the response is a single JSON object: - -```json -{ "status": "success" } -``` - -## Generate Embeddings - -```shell -POST /api/embed -``` - -Generate embeddings from a model - -### Parameters - -- `model`: name of model to generate embeddings from -- `input`: text or list of text to generate embeddings for - -Advanced parameters: - -- `truncate`: truncates the end of each input to fit within context length. Returns error if `false` and context length is exceeded. Defaults to `true` -- `options`: additional model parameters listed in the documentation for the [Modelfile](./modelfile.md#valid-parameters-and-values) such as `temperature` -- `keep_alive`: controls how long the model will stay loaded into memory following the request (default: `5m`) - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/embed -d '{ - "model": "all-minilm", - "input": "Why is the sky blue?" -}' -``` - -#### Response - -```json -{ - "model": "all-minilm", - "embeddings": [[ - 0.010071029, -0.0017594862, 0.05007221, 0.04692972, 0.054916814, - 0.008599704, 0.105441414, -0.025878139, 0.12958129, 0.031952348 - ]], - "total_duration": 14143917, - "load_duration": 1019500, - "prompt_eval_count": 8 -} -``` - -#### Request (Multiple input) - -```shell -curl http://localhost:11434/api/embed -d '{ - "model": "all-minilm", - "input": ["Why is the sky blue?", "Why is the grass green?"] -}' -``` - -#### Response - -```json -{ - "model": "all-minilm", - "embeddings": [[ - 0.010071029, -0.0017594862, 0.05007221, 0.04692972, 0.054916814, - 0.008599704, 0.105441414, -0.025878139, 0.12958129, 0.031952348 - ],[ - -0.0098027075, 0.06042469, 0.025257962, -0.006364387, 0.07272725, - 0.017194884, 0.09032035, -0.051705178, 0.09951512, 0.09072481 - ]] -} -``` - -## List Running Models -```shell -GET /api/ps -``` - -List models that are currently loaded into memory. - -#### Examples - -### Request - -```shell -curl http://localhost:11434/api/ps -``` - -#### Response - -A single JSON object will be returned. - -```json -{ - "models": [ - { - "name": "mistral:latest", - "model": "mistral:latest", - "size": 5137025024, - "digest": "2ae6f6dd7a3dd734790bbbf58b8909a606e0e7e97e94b7604e0aa7ae4490e6d8", - "details": { - "parent_model": "", - "format": "gguf", - "family": "llama", - "families": [ - "llama" - ], - "parameter_size": "7.2B", - "quantization_level": "Q4_0" - }, - "expires_at": "2024-06-04T14:38:31.83753-07:00", - "size_vram": 5137025024 - } - ] -} -``` - -## Generate Embedding - -> Note: this endpoint has been superseded by `/api/embed` - -```shell -POST /api/embeddings -``` - -Generate embeddings from a model - -### Parameters - -- `model`: name of model to generate embeddings from -- `prompt`: text to generate embeddings for - -Advanced parameters: - -- `options`: additional model parameters listed in the documentation for the [Modelfile](./modelfile.md#valid-parameters-and-values) such as `temperature` -- `keep_alive`: controls how long the model will stay loaded into memory following the request (default: `5m`) - -### Examples - -#### Request - -```shell -curl http://localhost:11434/api/embeddings -d '{ - "model": "all-minilm", - "prompt": "Here is an article about llamas..." -}' -``` - -#### Response - -```json -{ - "embedding": [ - 0.5670403838157654, 0.009260174818336964, 0.23178744316101074, -0.2916173040866852, -0.8924556970596313, - 0.8785552978515625, -0.34576427936553955, 0.5742510557174683, -0.04222835972905159, -0.137906014919281 - ] -} -``` diff --git a/ollama/docs/development.md b/ollama/docs/development.md deleted file mode 100755 index cd6c41a..0000000 --- a/ollama/docs/development.md +++ /dev/null @@ -1,150 +0,0 @@ -# Development - -Install required tools: - -- cmake version 3.24 or higher -- go version 1.22 or higher -- gcc version 11.4.0 or higher - -### MacOS - -```bash -brew install go cmake gcc -``` - -Optionally enable debugging and more verbose logging: - -```bash -# At build time -export CGO_CFLAGS="-g" - -# At runtime -export OLLAMA_DEBUG=1 -``` - -Get the required libraries and build the native LLM code: - -```bash -go generate ./... -``` - -Then build ollama: - -```bash -go build . -``` - -Now you can run `ollama`: - -```bash -./ollama -``` - -### Linux - -#### Linux CUDA (NVIDIA) - -_Your operating system distribution may already have packages for NVIDIA CUDA. Distro packages are often preferable, but instructions are distro-specific. Please consult distro-specific docs for dependencies if available!_ - -Install `cmake` and `golang` as well as [NVIDIA CUDA](https://developer.nvidia.com/cuda-downloads) -development and runtime packages. - -Typically the build scripts will auto-detect CUDA, however, if your Linux distro -or installation approach uses unusual paths, you can specify the location by -specifying an environment variable `CUDA_LIB_DIR` to the location of the shared -libraries, and `CUDACXX` to the location of the nvcc compiler. You can customize -a set of target CUDA architectures by setting `CMAKE_CUDA_ARCHITECTURES` (e.g. "50;60;70") - -Then generate dependencies: - -``` -go generate ./... -``` - -Then build the binary: - -``` -go build . -``` - -#### Linux ROCm (AMD) - -_Your operating system distribution may already have packages for AMD ROCm and CLBlast. Distro packages are often preferable, but instructions are distro-specific. Please consult distro-specific docs for dependencies if available!_ - -Install [CLBlast](https://github.com/CNugteren/CLBlast/blob/master/doc/installation.md) and [ROCm](https://rocm.docs.amd.com/en/latest/) development packages first, as well as `cmake` and `golang`. - -Typically the build scripts will auto-detect ROCm, however, if your Linux distro -or installation approach uses unusual paths, you can specify the location by -specifying an environment variable `ROCM_PATH` to the location of the ROCm -install (typically `/opt/rocm`), and `CLBlast_DIR` to the location of the -CLBlast install (typically `/usr/lib/cmake/CLBlast`). You can also customize -the AMD GPU targets by setting AMDGPU_TARGETS (e.g. `AMDGPU_TARGETS="gfx1101;gfx1102"`) - -``` -go generate ./... -``` - -Then build the binary: - -``` -go build . -``` - -ROCm requires elevated privileges to access the GPU at runtime. On most distros you can add your user account to the `render` group, or run as root. - -#### Advanced CPU Settings - -By default, running `go generate ./...` will compile a few different variations -of the LLM library based on common CPU families and vector math capabilities, -including a lowest-common-denominator which should run on almost any 64 bit CPU -somewhat slowly. At runtime, Ollama will auto-detect the optimal variation to -load. If you would like to build a CPU-based build customized for your -processor, you can set `OLLAMA_CUSTOM_CPU_DEFS` to the llama.cpp flags you would -like to use. For example, to compile an optimized binary for an Intel i9-9880H, -you might use: - -``` -OLLAMA_CUSTOM_CPU_DEFS="-DGGML_AVX=on -DGGML_AVX2=on -DGGML_F16C=on -DGGML_FMA=on" go generate ./... -go build . -``` - -#### Containerized Linux Build - -If you have Docker available, you can build linux binaries with `./scripts/build_linux.sh` which has the CUDA and ROCm dependencies included. The resulting binary is placed in `./dist` - -### Windows - -Note: The Windows build for Ollama is still under development. - -First, install required tools: - -- MSVC toolchain - C/C++ and cmake as minimal requirements -- Go version 1.22 or higher -- MinGW (pick one variant) with GCC. - - [MinGW-w64](https://www.mingw-w64.org/) - - [MSYS2](https://www.msys2.org/) -- The `ThreadJob` Powershell module: `Install-Module -Name ThreadJob -Scope CurrentUser` - -Then, build the `ollama` binary: - -```powershell -$env:CGO_ENABLED="1" -go generate ./... -go build . -``` - -#### Windows CUDA (NVIDIA) - -In addition to the common Windows development tools described above, install CUDA after installing MSVC. - -- [NVIDIA CUDA](https://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html) - - -#### Windows ROCm (AMD Radeon) - -In addition to the common Windows development tools described above, install AMDs HIP package after installing MSVC. - -- [AMD HIP](https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html) -- [Strawberry Perl](https://strawberryperl.com/) - -Lastly, add `ninja.exe` included with MSVC to the system path (e.g. `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja`). diff --git a/ollama/docs/docker.md b/ollama/docs/docker.md deleted file mode 100755 index 314666b..0000000 --- a/ollama/docs/docker.md +++ /dev/null @@ -1,71 +0,0 @@ -# Ollama Docker image - -### CPU only - -```bash -docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama -``` - -### Nvidia GPU -Install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installation). - -#### Install with Apt -1. Configure the repository -```bash -curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ - | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg -curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \ - | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ - | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list -sudo apt-get update -``` -2. Install the NVIDIA Container Toolkit packages -```bash -sudo apt-get install -y nvidia-container-toolkit -``` - -#### Install with Yum or Dnf -1. Configure the repository - -```bash -curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo \ - | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo -``` - -2. Install the NVIDIA Container Toolkit packages - -```bash -sudo yum install -y nvidia-container-toolkit -``` - -#### Configure Docker to use Nvidia driver -``` -sudo nvidia-ctk runtime configure --runtime=docker -sudo systemctl restart docker -``` - -#### Start the container - -```bash -docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama -``` - -### AMD GPU - -To run Ollama using Docker with AMD GPUs, use the `rocm` tag and the following command: - -``` -docker run -d --device /dev/kfd --device /dev/dri -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama:rocm -``` - -### Run model locally - -Now you can run a model: - -``` -docker exec -it ollama ollama run llama3.1 -``` - -### Try different models - -More models can be found on the [Ollama library](https://ollama.com/library). diff --git a/ollama/docs/faq.md b/ollama/docs/faq.md deleted file mode 100755 index 324116d..0000000 --- a/ollama/docs/faq.md +++ /dev/null @@ -1,279 +0,0 @@ -# FAQ - -## How can I upgrade Ollama? - -Ollama on macOS and Windows will automatically download updates. Click on the taskbar or menubar item and then click "Restart to update" to apply the update. Updates can also be installed by downloading the latest version [manually](https://ollama.com/download/). - -On Linux, re-run the install script: - -```shell -curl -fsSL https://ollama.com/install.sh | sh -``` - -## How can I view the logs? - -Review the [Troubleshooting](./troubleshooting.md) docs for more about using logs. - -## Is my GPU compatible with Ollama? - -Please refer to the [GPU docs](./gpu.md). - -## How can I specify the context window size? - -By default, Ollama uses a context window size of 2048 tokens. - -To change this when using `ollama run`, use `/set parameter`: - -``` -/set parameter num_ctx 4096 -``` - -When using the API, specify the `num_ctx` parameter: - -```shell -curl http://localhost:11434/api/generate -d '{ - "model": "llama3", - "prompt": "Why is the sky blue?", - "options": { - "num_ctx": 4096 - } -}' -``` - -## How can I tell if my model was loaded onto the GPU? - -Use the `ollama ps` command to see what models are currently loaded into memory. - -```shell -ollama ps -NAME ID SIZE PROCESSOR UNTIL -llama3:70b bcfb190ca3a7 42 GB 100% GPU 4 minutes from now -``` - -The `Processor` column will show which memory the model was loaded in to: -* `100% GPU` means the model was loaded entirely into the GPU -* `100% CPU` means the model was loaded entirely in system memory -* `48%/52% CPU/GPU` means the model was loaded partially onto both the GPU and into system memory - -## How do I configure Ollama server? - -Ollama server can be configured with environment variables. - -### Setting environment variables on Mac - -If Ollama is run as a macOS application, environment variables should be set using `launchctl`: - -1. For each environment variable, call `launchctl setenv`. - - ```bash - launchctl setenv OLLAMA_HOST "0.0.0.0" - ``` - -2. Restart Ollama application. - -### Setting environment variables on Linux - -If Ollama is run as a systemd service, environment variables should be set using `systemctl`: - -1. Edit the systemd service by calling `systemctl edit ollama.service`. This will open an editor. - -2. For each environment variable, add a line `Environment` under section `[Service]`: - - ```ini - [Service] - Environment="OLLAMA_HOST=0.0.0.0" - ``` - -3. Save and exit. - -4. Reload `systemd` and restart Ollama: - - ```bash - systemctl daemon-reload - systemctl restart ollama - ``` - -### Setting environment variables on Windows - -On Windows, Ollama inherits your user and system environment variables. - -1. First Quit Ollama by clicking on it in the task bar. - -2. Start the Settings (Windows 11) or Control Panel (Windows 10) application and search for _environment variables_. - -3. Click on _Edit environment variables for your account_. - -4. Edit or create a new variable for your user account for `OLLAMA_HOST`, `OLLAMA_MODELS`, etc. - -5. Click OK/Apply to save. - -6. Start the Ollama application from the Windows Start menu. - -## How do I use Ollama behind a proxy? - -Ollama is compatible with proxy servers if `HTTP_PROXY` or `HTTPS_PROXY` are configured. When using either variables, ensure it is set where `ollama serve` can access the values. When using `HTTPS_PROXY`, ensure the proxy certificate is installed as a system certificate. Refer to the section above for how to use environment variables on your platform. - -### How do I use Ollama behind a proxy in Docker? - -The Ollama Docker container image can be configured to use a proxy by passing `-e HTTPS_PROXY=https://proxy.example.com` when starting the container. - -Alternatively, the Docker daemon can be configured to use a proxy. Instructions are available for Docker Desktop on [macOS](https://docs.docker.com/desktop/settings/mac/#proxies), [Windows](https://docs.docker.com/desktop/settings/windows/#proxies), and [Linux](https://docs.docker.com/desktop/settings/linux/#proxies), and Docker [daemon with systemd](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy). - -Ensure the certificate is installed as a system certificate when using HTTPS. This may require a new Docker image when using a self-signed certificate. - -```dockerfile -FROM ollama/ollama -COPY my-ca.pem /usr/local/share/ca-certificates/my-ca.crt -RUN update-ca-certificates -``` - -Build and run this image: - -```shell -docker build -t ollama-with-ca . -docker run -d -e HTTPS_PROXY=https://my.proxy.example.com -p 11434:11434 ollama-with-ca -``` - -## Does Ollama send my prompts and answers back to ollama.com? - -No. Ollama runs locally, and conversation data does not leave your machine. - -## How can I expose Ollama on my network? - -Ollama binds 127.0.0.1 port 11434 by default. Change the bind address with the `OLLAMA_HOST` environment variable. - -Refer to the section [above](#how-do-i-configure-ollama-server) for how to set environment variables on your platform. - -## How can I use Ollama with a proxy server? - -Ollama runs an HTTP server and can be exposed using a proxy server such as Nginx. To do so, configure the proxy to forward requests and optionally set required headers (if not exposing Ollama on the network). For example, with Nginx: - -``` -server { - listen 80; - server_name example.com; # Replace with your domain or IP - location / { - proxy_pass http://localhost:11434; - proxy_set_header Host localhost:11434; - } -} -``` - -## How can I use Ollama with ngrok? - -Ollama can be accessed using a range of tools for tunneling tools. For example with Ngrok: - -```shell -ngrok http 11434 --host-header="localhost:11434" -``` - -## How can I use Ollama with Cloudflare Tunnel? - -To use Ollama with Cloudflare Tunnel, use the `--url` and `--http-host-header` flags: - -```shell -cloudflared tunnel --url http://localhost:11434 --http-host-header="localhost:11434" -``` - -## How can I allow additional web origins to access Ollama? - -Ollama allows cross-origin requests from `127.0.0.1` and `0.0.0.0` by default. Additional origins can be configured with `OLLAMA_ORIGINS`. - -Refer to the section [above](#how-do-i-configure-ollama-server) for how to set environment variables on your platform. - -## Where are models stored? - -- macOS: `~/.ollama/models` -- Linux: `/usr/share/ollama/.ollama/models` -- Windows: `C:\Users\%username%\.ollama\models` - -### How do I set them to a different location? - -If a different directory needs to be used, set the environment variable `OLLAMA_MODELS` to the chosen directory. - -Refer to the section [above](#how-do-i-configure-ollama-server) for how to set environment variables on your platform. - -## How can I use Ollama in Visual Studio Code? - -There is already a large collection of plugins available for VSCode as well as other editors that leverage Ollama. See the list of [extensions & plugins](https://github.com/ollama/ollama#extensions--plugins) at the bottom of the main repository readme. - -## How do I use Ollama with GPU acceleration in Docker? - -The Ollama Docker container can be configured with GPU acceleration in Linux or Windows (with WSL2). This requires the [nvidia-container-toolkit](https://github.com/NVIDIA/nvidia-container-toolkit). See [ollama/ollama](https://hub.docker.com/r/ollama/ollama) for more details. - -GPU acceleration is not available for Docker Desktop in macOS due to the lack of GPU passthrough and emulation. - -## Why is networking slow in WSL2 on Windows 10? - -This can impact both installing Ollama, as well as downloading models. - -Open `Control Panel > Networking and Internet > View network status and tasks` and click on `Change adapter settings` on the left panel. Find the `vEthernel (WSL)` adapter, right click and select `Properties`. -Click on `Configure` and open the `Advanced` tab. Search through each of the properties until you find `Large Send Offload Version 2 (IPv4)` and `Large Send Offload Version 2 (IPv6)`. *Disable* both of these -properties. - -## How can I preload a model into Ollama to get faster response times? - -If you are using the API you can preload a model by sending the Ollama server an empty request. This works with both the `/api/generate` and `/api/chat` API endpoints. - -To preload the mistral model using the generate endpoint, use: -```shell -curl http://localhost:11434/api/generate -d '{"model": "mistral"}' -``` - -To use the chat completions endpoint, use: -```shell -curl http://localhost:11434/api/chat -d '{"model": "mistral"}' -``` - -To preload a model using the CLI, use the command: -```shell -ollama run llama3.1 "" -``` - -## How do I keep a model loaded in memory or make it unload immediately? - -By default models are kept in memory for 5 minutes before being unloaded. This allows for quicker response times if you are making numerous requests to the LLM. You may, however, want to free up the memory before the 5 minutes have elapsed or keep the model loaded indefinitely. Use the `keep_alive` parameter with either the `/api/generate` and `/api/chat` API endpoints to control how long the model is left in memory. - -The `keep_alive` parameter can be set to: -* a duration string (such as "10m" or "24h") -* a number in seconds (such as 3600) -* any negative number which will keep the model loaded in memory (e.g. -1 or "-1m") -* '0' which will unload the model immediately after generating a response - -For example, to preload a model and leave it in memory use: -```shell -curl http://localhost:11434/api/generate -d '{"model": "llama3", "keep_alive": -1}' -``` - -To unload the model and free up memory use: -```shell -curl http://localhost:11434/api/generate -d '{"model": "llama3", "keep_alive": 0}' -``` - -Alternatively, you can change the amount of time all models are loaded into memory by setting the `OLLAMA_KEEP_ALIVE` environment variable when starting the Ollama server. The `OLLAMA_KEEP_ALIVE` variable uses the same parameter types as the `keep_alive` parameter types mentioned above. Refer to section explaining [how to configure the Ollama server](#how-do-i-configure-ollama-server) to correctly set the environment variable. - -If you wish to override the `OLLAMA_KEEP_ALIVE` setting, use the `keep_alive` API parameter with the `/api/generate` or `/api/chat` API endpoints. - -## How do I manage the maximum number of requests the Ollama server can queue? - -If too many requests are sent to the server, it will respond with a 503 error indicating the server is overloaded. You can adjust how many requests may be queue by setting `OLLAMA_MAX_QUEUE`. - -## How does Ollama handle concurrent requests? - -Ollama supports two levels of concurrent processing. If your system has sufficient available memory (system memory when using CPU inference, or VRAM for GPU inference) then multiple models can be loaded at the same time. For a given model, if there is sufficient available memory when the model is loaded, it is configured to allow parallel request processing. - -If there is insufficient available memory to load a new model request while one or more models are already loaded, all new requests will be queued until the new model can be loaded. As prior models become idle, one or more will be unloaded to make room for the new model. Queued requests will be processed in order. When using GPU inference new models must be able to completely fit in VRAM to allow concurrent model loads. - -Parallel request processing for a given model results in increasing the context size by the number of parallel requests. For example, a 2K context with 4 parallel requests will result in an 8K context and additional memory allocation. - -The following server settings may be used to adjust how Ollama handles concurrent requests on most platforms: - -- `OLLAMA_MAX_LOADED_MODELS` - The maximum number of models that can be loaded concurrently provided they fit in available memory. The default is 3 * the number of GPUs or 3 for CPU inference. -- `OLLAMA_NUM_PARALLEL` - The maximum number of parallel requests each model will process at the same time. The default will auto-select either 4 or 1 based on available memory. -- `OLLAMA_MAX_QUEUE` - The maximum number of requests Ollama will queue when busy before rejecting additional requests. The default is 512 - -Note: Windows with Radeon GPUs currently default to 1 model maximum due to limitations in ROCm v5.7 for available VRAM reporting. Once ROCm v6.2 is available, Windows Radeon will follow the defaults above. You may enable concurrent model loads on Radeon on Windows, but ensure you don't load more models than will fit into your GPUs VRAM. - -## How does Ollama load models on multiple GPUs? - -Installing multiple GPUs of the same brand can be a great way to increase your available VRAM to load larger models. When you load a new model, Ollama evaluates the required VRAM for the model against what is currently available. If the model will entirely fit on any single GPU, Ollama will load the model on that GPU. This typically provides the best performance as it reduces the amount of data transfering across the PCI bus during inference. If the model does not fit entirely on one GPU, then it will be spread across all the available GPUs. \ No newline at end of file diff --git a/ollama/docs/gpu.md b/ollama/docs/gpu.md deleted file mode 100755 index e669ea3..0000000 --- a/ollama/docs/gpu.md +++ /dev/null @@ -1,113 +0,0 @@ -# GPU -## Nvidia -Ollama supports Nvidia GPUs with compute capability 5.0+. - -Check your compute compatibility to see if your card is supported: -[https://developer.nvidia.com/cuda-gpus](https://developer.nvidia.com/cuda-gpus) - -| Compute Capability | Family | Cards | -| ------------------ | ------------------- | ----------------------------------------------------------------------------------------------------------- | -| 9.0 | NVIDIA | `H100` | -| 8.9 | GeForce RTX 40xx | `RTX 4090` `RTX 4080 SUPER` `RTX 4080` `RTX 4070 Ti SUPER` `RTX 4070 Ti` `RTX 4070 SUPER` `RTX 4070` `RTX 4060 Ti` `RTX 4060` | -| | NVIDIA Professional | `L4` `L40` `RTX 6000` | -| 8.6 | GeForce RTX 30xx | `RTX 3090 Ti` `RTX 3090` `RTX 3080 Ti` `RTX 3080` `RTX 3070 Ti` `RTX 3070` `RTX 3060 Ti` `RTX 3060` | -| | NVIDIA Professional | `A40` `RTX A6000` `RTX A5000` `RTX A4000` `RTX A3000` `RTX A2000` `A10` `A16` `A2` | -| 8.0 | NVIDIA | `A100` `A30` | -| 7.5 | GeForce GTX/RTX | `GTX 1650 Ti` `TITAN RTX` `RTX 2080 Ti` `RTX 2080` `RTX 2070` `RTX 2060` | -| | NVIDIA Professional | `T4` `RTX 5000` `RTX 4000` `RTX 3000` `T2000` `T1200` `T1000` `T600` `T500` | -| | Quadro | `RTX 8000` `RTX 6000` `RTX 5000` `RTX 4000` | -| 7.0 | NVIDIA | `TITAN V` `V100` `Quadro GV100` | -| 6.1 | NVIDIA TITAN | `TITAN Xp` `TITAN X` | -| | GeForce GTX | `GTX 1080 Ti` `GTX 1080` `GTX 1070 Ti` `GTX 1070` `GTX 1060` `GTX 1050 Ti` `GTX 1050` | -| | Quadro | `P6000` `P5200` `P4200` `P3200` `P5000` `P4000` `P3000` `P2200` `P2000` `P1000` `P620` `P600` `P500` `P520` | -| | Tesla | `P40` `P4` | -| 6.0 | NVIDIA | `Tesla P100` `Quadro GP100` | -| 5.2 | GeForce GTX | `GTX TITAN X` `GTX 980 Ti` `GTX 980` `GTX 970` `GTX 960` `GTX 950` | -| | Quadro | `M6000 24GB` `M6000` `M5000` `M5500M` `M4000` `M2200` `M2000` `M620` | -| | Tesla | `M60` `M40` | -| 5.0 | GeForce GTX | `GTX 750 Ti` `GTX 750` `NVS 810` | -| | Quadro | `K2200` `K1200` `K620` `M1200` `M520` `M5000M` `M4000M` `M3000M` `M2000M` `M1000M` `K620M` `M600M` `M500M` | - - -### GPU Selection - -If you have multiple NVIDIA GPUs in your system and want to limit Ollama to use -a subset, you can set `CUDA_VISIBLE_DEVICES` to a comma separated list of GPUs. -Numeric IDs may be used, however ordering may vary, so UUIDs are more reliable. -You can discover the UUID of your GPUs by running `nvidia-smi -L` If you want to -ignore the GPUs and force CPU usage, use an invalid GPU ID (e.g., "-1") - -### Laptop Suspend Resume - -On linux, after a suspend/resume cycle, sometimes Ollama will fail to discover -your NVIDIA GPU, and fallback to running on the CPU. You can workaround this -driver bug by reloading the NVIDIA UVM driver with `sudo rmmod nvidia_uvm && -sudo modprobe nvidia_uvm` - -## AMD Radeon -Ollama supports the following AMD GPUs: - -### Linux Support -| Family | Cards and accelerators | -| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| AMD Radeon RX | `7900 XTX` `7900 XT` `7900 GRE` `7800 XT` `7700 XT` `7600 XT` `7600` `6950 XT` `6900 XTX` `6900XT` `6800 XT` `6800` `Vega 64` `Vega 56` | -| AMD Radeon PRO | `W7900` `W7800` `W7700` `W7600` `W7500` `W6900X` `W6800X Duo` `W6800X` `W6800` `V620` `V420` `V340` `V320` `Vega II Duo` `Vega II` `VII` `SSG` | -| AMD Instinct | `MI300X` `MI300A` `MI300` `MI250X` `MI250` `MI210` `MI200` `MI100` `MI60` `MI50` | - -### Windows Support -With ROCm v6.1, the following GPUs are supported on Windows. - -| Family | Cards and accelerators | -| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| AMD Radeon RX | `7900 XTX` `7900 XT` `7900 GRE` `7800 XT` `7700 XT` `7600 XT` `7600` `6950 XT` `6900 XTX` `6900XT` `6800 XT` `6800` | -| AMD Radeon PRO | `W7900` `W7800` `W7700` `W7600` `W7500` `W6900X` `W6800X Duo` `W6800X` `W6800` `V620` | - - -### Overrides on Linux -Ollama leverages the AMD ROCm library, which does not support all AMD GPUs. In -some cases you can force the system to try to use a similar LLVM target that is -close. For example The Radeon RX 5400 is `gfx1034` (also known as 10.3.4) -however, ROCm does not currently support this target. The closest support is -`gfx1030`. You can use the environment variable `HSA_OVERRIDE_GFX_VERSION` with -`x.y.z` syntax. So for example, to force the system to run on the RX 5400, you -would set `HSA_OVERRIDE_GFX_VERSION="10.3.0"` as an environment variable for the -server. If you have an unsupported AMD GPU you can experiment using the list of -supported types below. - -At this time, the known supported GPU types on linux are the following LLVM Targets. -This table shows some example GPUs that map to these LLVM targets: -| **LLVM Target** | **An Example GPU** | -|-----------------|---------------------| -| gfx900 | Radeon RX Vega 56 | -| gfx906 | Radeon Instinct MI50 | -| gfx908 | Radeon Instinct MI100 | -| gfx90a | Radeon Instinct MI210 | -| gfx940 | Radeon Instinct MI300 | -| gfx941 | | -| gfx942 | | -| gfx1030 | Radeon PRO V620 | -| gfx1100 | Radeon PRO W7900 | -| gfx1101 | Radeon PRO W7700 | -| gfx1102 | Radeon RX 7600 | - -AMD is working on enhancing ROCm v6 to broaden support for families of GPUs in a -future release which should increase support for more GPUs. - -Reach out on [Discord](https://discord.gg/ollama) or file an -[issue](https://github.com/ollama/ollama/issues) for additional help. - -### GPU Selection - -If you have multiple AMD GPUs in your system and want to limit Ollama to use a -subset, you can set `HIP_VISIBLE_DEVICES` to a comma separated list of GPUs. -You can see the list of devices with `rocminfo`. If you want to ignore the GPUs -and force CPU usage, use an invalid GPU ID (e.g., "-1") - -### Container Permission - -In some Linux distributions, SELinux can prevent containers from -accessing the AMD GPU devices. On the host system you can run -`sudo setsebool container_use_devices=1` to allow containers to use devices. - -### Metal (Apple GPUs) -Ollama supports GPU acceleration on Apple devices via the Metal API. diff --git a/ollama/docs/import.md b/ollama/docs/import.md deleted file mode 100755 index f34f09a..0000000 --- a/ollama/docs/import.md +++ /dev/null @@ -1,88 +0,0 @@ -# Import - -GGUF models and select Safetensors models can be imported directly into Ollama. - -## Import GGUF - -A binary GGUF file can be imported directly into Ollama through a Modelfile. - -```dockerfile -FROM /path/to/file.gguf -``` - -## Import Safetensors - -If the model being imported is one of these architectures, it can be imported directly into Ollama through a Modelfile: - - - LlamaForCausalLM - - MistralForCausalLM - - GemmaForCausalLM - -```dockerfile -FROM /path/to/safetensors/directory -``` - -For architectures not directly convertable by Ollama, see llama.cpp's [guide](https://github.com/ggerganov/llama.cpp/blob/master/README.md#prepare-and-quantize) on conversion. After conversion, see [Import GGUF](#import-gguf). - -## Automatic Quantization - -> [!NOTE] -> Automatic quantization requires v0.1.35 or higher. - -Ollama is capable of quantizing FP16 or FP32 models to any of the supported quantizations with the `-q/--quantize` flag in `ollama create`. - -```dockerfile -FROM /path/to/my/gemma/f16/model -``` - -```shell -$ ollama create -q Q4_K_M mymodel -transferring model data -quantizing F16 model to Q4_K_M -creating new layer sha256:735e246cc1abfd06e9cdcf95504d6789a6cd1ad7577108a70d9902fef503c1bd -creating new layer sha256:0853f0ad24e5865173bbf9ffcc7b0f5d56b66fd690ab1009867e45e7d2c4db0f -writing manifest -success -``` - -### Supported Quantizations - -- `Q4_0` -- `Q4_1` -- `Q5_0` -- `Q5_1` -- `Q8_0` - -#### K-means Quantizations - -- `Q3_K_S` -- `Q3_K_M` -- `Q3_K_L` -- `Q4_K_S` -- `Q4_K_M` -- `Q5_K_S` -- `Q5_K_M` -- `Q6_K` - -## Template Detection - -> [!NOTE] -> Template detection requires v0.1.42 or higher. - -Ollama uses model metadata, specifically `tokenizer.chat_template`, to automatically create a template appropriate for the model you're importing. - -```dockerfile -FROM /path/to/my/gemma/model -``` - -```shell -$ ollama create mymodel -transferring model data -using autodetected template gemma-instruct -creating new layer sha256:baa2a0edc27d19cc6b7537578a9a7ba1a4e3214dc185ed5ae43692b319af7b84 -creating new layer sha256:ba66c3309914dbef07e5149a648fd1877f030d337a4f240d444ea335008943cb -writing manifest -success -``` - -Defining a template in the Modelfile will disable this feature which may be useful if you want to use a different template than the autodetected one. diff --git a/ollama/docs/linux.md b/ollama/docs/linux.md deleted file mode 100755 index ec73065..0000000 --- a/ollama/docs/linux.md +++ /dev/null @@ -1,143 +0,0 @@ -# Ollama on Linux - -## Install - -Install Ollama running this one-liner: - -> - -```bash -curl -fsSL https://ollama.com/install.sh | sh -``` - -## AMD Radeon GPU support - -While AMD has contributed the `amdgpu` driver upstream to the official linux -kernel source, the version is older and may not support all ROCm features. We -recommend you install the latest driver from -https://www.amd.com/en/support/linux-drivers for best support of your Radeon -GPU. - -## Manual install - -### Download the `ollama` binary - -Ollama is distributed as a self-contained binary. Download it to a directory in your PATH: - -```bash -sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/bin/ollama -sudo chmod +x /usr/bin/ollama -``` - -### Adding Ollama as a startup service (recommended) - -Create a user for Ollama: - -```bash -sudo useradd -r -s /bin/false -m -d /usr/share/ollama ollama -``` - -Create a service file in `/etc/systemd/system/ollama.service`: - -```ini -[Unit] -Description=Ollama Service -After=network-online.target - -[Service] -ExecStart=/usr/bin/ollama serve -User=ollama -Group=ollama -Restart=always -RestartSec=3 - -[Install] -WantedBy=default.target -``` - -Then start the service: - -```bash -sudo systemctl daemon-reload -sudo systemctl enable ollama -``` - -### Install CUDA drivers (optional – for Nvidia GPUs) - -[Download and install](https://developer.nvidia.com/cuda-downloads) CUDA. - -Verify that the drivers are installed by running the following command, which should print details about your GPU: - -```bash -nvidia-smi -``` - -### Install ROCm (optional - for Radeon GPUs) -[Download and Install](https://rocm.docs.amd.com/projects/install-on-linux/en/latest/tutorial/quick-start.html) - -Make sure to install ROCm v6 - -### Start Ollama - -Start Ollama using `systemd`: - -```bash -sudo systemctl start ollama -``` - -## Update - -Update ollama by running the install script again: - -```bash -curl -fsSL https://ollama.com/install.sh | sh -``` - -Or by downloading the ollama binary: - -```bash -sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/bin/ollama -sudo chmod +x /usr/bin/ollama -``` - -## Installing specific versions - -Use `OLLAMA_VERSION` environment variable with the install script to install a specific version of Ollama, including pre-releases. You can find the version numbers in the [releases page](https://github.com/ollama/ollama/releases). - -For example: - -``` -curl -fsSL https://ollama.com/install.sh | OLLAMA_VERSION=0.1.32 sh -``` - -## Viewing logs - -To view logs of Ollama running as a startup service, run: - -```bash -journalctl -e -u ollama -``` - -## Uninstall - -Remove the ollama service: - -```bash -sudo systemctl stop ollama -sudo systemctl disable ollama -sudo rm /etc/systemd/system/ollama.service -``` - -Remove the ollama binary from your bin directory (either `/usr/local/bin`, `/usr/bin`, or `/bin`): - -```bash -sudo rm $(which ollama) -``` - -Remove the downloaded models and Ollama service user and group: - -```bash -sudo rm -r /usr/share/ollama -sudo userdel ollama -sudo groupdel ollama -``` diff --git a/ollama/docs/modelfile.md b/ollama/docs/modelfile.md deleted file mode 100755 index 852bf96..0000000 --- a/ollama/docs/modelfile.md +++ /dev/null @@ -1,227 +0,0 @@ -# Ollama Model File - -> [!NOTE] -> `Modelfile` syntax is in development - -A model file is the blueprint to create and share models with Ollama. - -## Table of Contents - -- [Format](#format) -- [Examples](#examples) -- [Instructions](#instructions) - - [FROM (Required)](#from-required) - - [Build from llama3](#build-from-llama3) - - [Build from a bin file](#build-from-a-bin-file) - - [PARAMETER](#parameter) - - [Valid Parameters and Values](#valid-parameters-and-values) - - [TEMPLATE](#template) - - [Template Variables](#template-variables) - - [SYSTEM](#system) - - [ADAPTER](#adapter) - - [LICENSE](#license) - - [MESSAGE](#message) -- [Notes](#notes) - -## Format - -The format of the `Modelfile`: - -```modelfile -# comment -INSTRUCTION arguments -``` - -| Instruction | Description | -| ----------------------------------- | -------------------------------------------------------------- | -| [`FROM`](#from-required) (required) | Defines the base model to use. | -| [`PARAMETER`](#parameter) | Sets the parameters for how Ollama will run the model. | -| [`TEMPLATE`](#template) | The full prompt template to be sent to the model. | -| [`SYSTEM`](#system) | Specifies the system message that will be set in the template. | -| [`ADAPTER`](#adapter) | Defines the (Q)LoRA adapters to apply to the model. | -| [`LICENSE`](#license) | Specifies the legal license. | -| [`MESSAGE`](#message) | Specify message history. | - -## Examples - -### Basic `Modelfile` - -An example of a `Modelfile` creating a mario blueprint: - -```modelfile -FROM llama3 -# sets the temperature to 1 [higher is more creative, lower is more coherent] -PARAMETER temperature 1 -# sets the context window size to 4096, this controls how many tokens the LLM can use as context to generate the next token -PARAMETER num_ctx 4096 - -# sets a custom system message to specify the behavior of the chat assistant -SYSTEM You are Mario from super mario bros, acting as an assistant. -``` - -To use this: - -1. Save it as a file (e.g. `Modelfile`) -2. `ollama create choose-a-model-name -f '` -3. `ollama run choose-a-model-name` -4. Start using the model! - -More examples are available in the [examples directory](../examples). - -To view the Modelfile of a given model, use the `ollama show --modelfile` command. - - ```bash - > ollama show --modelfile llama3 - # Modelfile generated by "ollama show" - # To build a new Modelfile based on this one, replace the FROM line with: - # FROM llama3:latest - FROM /Users/pdevine/.ollama/models/blobs/sha256-00e1317cbf74d901080d7100f57580ba8dd8de57203072dc6f668324ba545f29 - TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|> - - {{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|> - - {{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|> - - {{ .Response }}<|eot_id|>""" - PARAMETER stop "<|start_header_id|>" - PARAMETER stop "<|end_header_id|>" - PARAMETER stop "<|eot_id|>" - PARAMETER stop "<|reserved_special_token" - ``` - -## Instructions - -### FROM (Required) - -The `FROM` instruction defines the base model to use when creating a model. - -```modelfile -FROM : -``` - -#### Build from llama3 - -```modelfile -FROM llama3 -``` - -A list of available base models: - - -#### Build from a `bin` file - -```modelfile -FROM ./ollama-model.bin -``` - -This bin file location should be specified as an absolute path or relative to the `Modelfile` location. - -### PARAMETER - -The `PARAMETER` instruction defines a parameter that can be set when the model is run. - -```modelfile -PARAMETER -``` - -#### Valid Parameters and Values - -| Parameter | Description | Value Type | Example Usage | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------------- | -| mirostat | Enable Mirostat sampling for controlling perplexity. (default: 0, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0) | int | mirostat 0 | -| mirostat_eta | Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive. (Default: 0.1) | float | mirostat_eta 0.1 | -| mirostat_tau | Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text. (Default: 5.0) | float | mirostat_tau 5.0 | -| num_ctx | Sets the size of the context window used to generate the next token. (Default: 2048) | int | num_ctx 4096 | -| repeat_last_n | Sets how far back for the model to look back to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx) | int | repeat_last_n 64 | -| repeat_penalty | Sets how strongly to penalize repetitions. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. (Default: 1.1) | float | repeat_penalty 1.1 | -| temperature | The temperature of the model. Increasing the temperature will make the model answer more creatively. (Default: 0.8) | float | temperature 0.7 | -| seed | Sets the random number seed to use for generation. Setting this to a specific number will make the model generate the same text for the same prompt. (Default: 0) | int | seed 42 | -| stop | Sets the stop sequences to use. When this pattern is encountered the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate `stop` parameters in a modelfile. | string | stop "AI assistant:" | -| tfs_z | Tail free sampling is used to reduce the impact of less probable tokens from the output. A higher value (e.g., 2.0) will reduce the impact more, while a value of 1.0 disables this setting. (default: 1) | float | tfs_z 1 | -| num_predict | Maximum number of tokens to predict when generating text. (Default: 128, -1 = infinite generation, -2 = fill context) | int | num_predict 42 | -| top_k | Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40) | int | top_k 40 | -| top_p | Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text. (Default: 0.9) | float | top_p 0.9 | -| min_p | Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter *p* represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with *p*=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out. (Default: 0.0) | float | min_p 0.05 | - -### TEMPLATE - -`TEMPLATE` of the full prompt template to be passed into the model. It may include (optionally) a system message, a user's message and the response from the model. Note: syntax may be model specific. Templates use Go [template syntax](https://pkg.go.dev/text/template). - -#### Template Variables - -| Variable | Description | -| ----------------- | --------------------------------------------------------------------------------------------- | -| `{{ .System }}` | The system message used to specify custom behavior. | -| `{{ .Prompt }}` | The user prompt message. | -| `{{ .Response }}` | The response from the model. When generating a response, text after this variable is omitted. | - -``` -TEMPLATE """{{ if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -""" -``` - -### SYSTEM - -The `SYSTEM` instruction specifies the system message to be used in the template, if applicable. - -```modelfile -SYSTEM """""" -``` - -### ADAPTER - -The `ADAPTER` instruction is an optional instruction that specifies any LoRA adapter that should apply to the base model. The value of this instruction should be an absolute path or a path relative to the Modelfile and the file must be in a GGML file format. The adapter should be tuned from the base model otherwise the behaviour is undefined. - -```modelfile -ADAPTER ./ollama-lora.bin -``` - -### LICENSE - -The `LICENSE` instruction allows you to specify the legal license under which the model used with this Modelfile is shared or distributed. - -```modelfile -LICENSE """ - -""" -``` - -### MESSAGE - -The `MESSAGE` instruction allows you to specify a message history for the model to use when responding. Use multiple iterations of the MESSAGE command to build up a conversation which will guide the model to answer in a similar way. - -```modelfile -MESSAGE -``` - -#### Valid roles - -| Role | Description | -| --------- | ------------------------------------------------------------ | -| system | Alternate way of providing the SYSTEM message for the model. | -| user | An example message of what the user could have asked. | -| assistant | An example message of how the model should respond. | - - -#### Example conversation - -```modelfile -MESSAGE user Is Toronto in Canada? -MESSAGE assistant yes -MESSAGE user Is Sacramento in Canada? -MESSAGE assistant no -MESSAGE user Is Ontario in Canada? -MESSAGE assistant yes -``` - - -## Notes - -- the **`Modelfile` is not case sensitive**. In the examples, uppercase instructions are used to make it easier to distinguish it from arguments. -- Instructions can be in any order. In the examples, the `FROM` instruction is first to keep it easily readable. - -[1]: https://ollama.com/library diff --git a/ollama/docs/openai.md b/ollama/docs/openai.md deleted file mode 100755 index 7b3a3f3..0000000 --- a/ollama/docs/openai.md +++ /dev/null @@ -1,303 +0,0 @@ -# OpenAI compatibility - -> **Note:** OpenAI compatibility is experimental and is subject to major adjustments including breaking changes. For fully-featured access to the Ollama API, see the Ollama [Python library](https://github.com/ollama/ollama-python), [JavaScript library](https://github.com/ollama/ollama-js) and [REST API](https://github.com/ollama/ollama/blob/main/docs/api.md). - -Ollama provides experimental compatibility with parts of the [OpenAI API](https://platform.openai.com/docs/api-reference) to help connect existing applications to Ollama. - -## Usage - -### OpenAI Python library - -```python -from openai import OpenAI - -client = OpenAI( - base_url='http://localhost:11434/v1/', - - # required but ignored - api_key='ollama', -) - -chat_completion = client.chat.completions.create( - messages=[ - { - 'role': 'user', - 'content': 'Say this is a test', - } - ], - model='llama3', -) - -response = client.chat.completions.create( - model="llava", - messages=[ - { - "role": "user", - "content": [ - {"type": "text", "text": "What's in this image?"}, - { - "type": "image_url", - "image_url": "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", - }, - ], - } - ], - max_tokens=300, -) - -completion = client.completions.create( - model="llama3", - prompt="Say this is a test", -) - -list_completion = client.models.list() - -model = client.models.retrieve("llama3") - -embeddings = client.embeddings.create( - model="all-minilm", - input=["why is the sky blue?", "why is the grass green?"], -) -``` - -### OpenAI JavaScript library - -```javascript -import OpenAI from 'openai' - -const openai = new OpenAI({ - baseURL: 'http://localhost:11434/v1/', - - // required but ignored - apiKey: 'ollama', -}) - -const chatCompletion = await openai.chat.completions.create({ - messages: [{ role: 'user', content: 'Say this is a test' }], - model: 'llama3', -}) - -const response = await openai.chat.completions.create({ - model: "llava", - messages: [ - { - role: "user", - content: [ - { type: "text", text: "What's in this image?" }, - { - type: "image_url", - image_url: "iVBORw0KGgoAAAANSUhEUgAAAG0AAABmCAYAAADBPx+VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAA3VSURBVHgB7Z27r0zdG8fX743i1bi1ikMoFMQloXRpKFFIqI7LH4BEQ+NWIkjQuSWCRIEoULk0gsK1kCBI0IhrQVT7tz/7zZo888yz1r7MnDl7z5xvsjkzs2fP3uu71nNfa7lkAsm7d++Sffv2JbNmzUqcc8m0adOSzZs3Z+/XES4ZckAWJEGWPiCxjsQNLWmQsWjRIpMseaxcuTKpG/7HP27I8P79e7dq1ars/yL4/v27S0ejqwv+cUOGEGGpKHR37tzJCEpHV9tnT58+dXXCJDdECBE2Ojrqjh071hpNECjx4cMHVycM1Uhbv359B2F79+51586daxN/+pyRkRFXKyRDAqxEp4yMlDDzXG1NPnnyJKkThoK0VFd1ELZu3TrzXKxKfW7dMBQ6bcuWLW2v0VlHjx41z717927ba22U9APcw7Nnz1oGEPeL3m3p2mTAYYnFmMOMXybPPXv2bNIPpFZr1NHn4HMw0KRBjg9NuRw95s8PEcz/6DZELQd/09C9QGq5RsmSRybqkwHGjh07OsJSsYYm3ijPpyHzoiacg35MLdDSIS/O1yM778jOTwYUkKNHWUzUWaOsylE00MyI0fcnOwIdjvtNdW/HZwNLGg+sR1kMepSNJXmIwxBZiG8tDTpEZzKg0GItNsosY8USkxDhD0Rinuiko2gfL/RbiD2LZAjU9zKQJj8RDR0vJBR1/Phx9+PHj9Z7REF4nTZkxzX4LCXHrV271qXkBAPGfP/atWvu/PnzHe4C97F48eIsRLZ9+3a3f/9+87dwP1JxaF7/3r17ba+5l4EcaVo0lj3SBq5kGTJSQmLWMjgYNei2GPT1MuMqGTDEFHzeQSP2wi/jGnkmPJ/nhccs44jvDAxpVcxnq0F6eT8h4ni/iIWpR5lPyA6ETkNXoSukvpJAD3AsXLiwpZs49+fPn5ke4j10TqYvegSfn0OnafC+Tv9ooA/JPkgQysqQNBzagXY55nO/oa1F7qvIPWkRL12WRpMWUvpVDYmxAPehxWSe8ZEXL20sadYIozfmNch4QJPAfeJgW3rNsnzphBKNJM2KKODo1rVOMRYik5ETy3ix4qWNI81qAAirizgMIc+yhTytx0JWZuNI03qsrgWlGtwjoS9XwgUhWGyhUaRZZQNNIEwCiXD16tXcAHUs79co0vSD8rrJCIW98pzvxpAWyyo3HYwqS0+H0BjStClcZJT5coMm6D2LOF8TolGJtK9fvyZpyiC5ePFi9nc/oJU4eiEP0jVoAnHa9wyJycITMP78+eMeP37sXrx44d6+fdt6f82aNdkx1pg9e3Zb5W+RSRE+n+VjksQWifvVaTKFhn5O8my63K8Qabdv33b379/PiAP//vuvW7BggZszZ072/+TJk91YgkafPn166zXB1rQHFvouAWHq9z3SEevSUerqCn2/dDCeta2jxYbr69evk4MHDyY7d+7MjhMnTiTPnz9Pfv/+nfQT2ggpO2dMF8cghuoM7Ygj5iWCqRlGFml0QC/ftGmTmzt3rmsaKDsgBSPh0/8yPeLLBihLkOKJc0jp8H8vUzcxIA1k6QJ/c78tWEyj5P3o4u9+jywNPdJi5rAH9x0KHcl4Hg570eQp3+vHXGyrmEeigzQsQsjavXt38ujRo44LQuDDhw+TW7duRS1HGgMxhNXHgflaNTOsHyKvHK5Ijo2jbFjJBQK9YwFd6RVMzfgRBmEfP37suBBm/p49e1qjEP2mwTViNRo0VJWH1deMXcNK08uUjVUu7s/zRaL+oLNxz1bpANco4npUgX4G2eFbpDFyQoQxojBCpEGSytmOH8qrH5Q9vuzD6ofQylkCUmh8DBAr+q8JCyVNtWQIidKQE9wNtLSQnS4jDSsxNHogzFuQBw4cyM61UKVsjfr3ooBkPSqqQHesUPWVtzi9/vQi1T+rJj7WiTz4Pt/l3LxUkr5P2VYZaZ4URpsE+st/dujQoaBBYokbrz/8TJNQYLSonrPS9kUaSkPeZyj1AWSj+d+VBoy1pIWVNed8P0Ll/ee5HdGRhrHhR5GGN0r4LGZBaj8oFDJitBTJzIZgFcmU0Y8ytWMZMzJOaXUSrUs5RxKnrxmbb5YXO9VGUhtpXldhEUogFr3IzIsvlpmdosVcGVGXFWp2oU9kLFL3dEkSz6NHEY1sjSRdIuDFWEhd8KxFqsRi1uM/nz9/zpxnwlESONdg6dKlbsaMGS4EHFHtjFIDHwKOo46l4TxSuxgDzi+rE2jg+BaFruOX4HXa0Nnf1lwAPufZeF8/r6zD97WK2qFnGjBxTw5qNGPxT+5T/r7/7RawFC3j4vTp09koCxkeHjqbHJqArmH5UrFKKksnxrK7FuRIs8STfBZv+luugXZ2pR/pP9Ois4z+TiMzUUkUjD0iEi1fzX8GmXyuxUBRcaUfykV0YZnlJGKQpOiGB76x5GeWkWWJc3mOrK6S7xdND+W5N6XyaRgtWJFe13GkaZnKOsYqGdOVVVbGupsyA/l7emTLHi7vwTdirNEt0qxnzAvBFcnQF16xh/TMpUuXHDowhlA9vQVraQhkudRdzOnK+04ZSP3DUhVSP61YsaLtd/ks7ZgtPcXqPqEafHkdqa84X6aCeL7YWlv6edGFHb+ZFICPlljHhg0bKuk0CSvVznWsotRu433alNdFrqG45ejoaPCaUkWERpLXjzFL2Rpllp7PJU2a/v7Ab8N05/9t27Z16KUqoFGsxnI9EosS2niSYg9SpU6B4JgTrvVW1flt1sT+0ADIJU2maXzcUTraGCRaL1Wp9rUMk16PMom8QhruxzvZIegJjFU7LLCePfS8uaQdPny4jTTL0dbee5mYokQsXTIWNY46kuMbnt8Kmec+LGWtOVIl9cT1rCB0V8WqkjAsRwta93TbwNYoGKsUSChN44lgBNCoHLHzquYKrU6qZ8lolCIN0Rh6cP0Q3U6I6IXILYOQI513hJaSKAorFpuHXJNfVlpRtmYBk1Su1obZr5dnKAO+L10Hrj3WZW+E3qh6IszE37F6EB+68mGpvKm4eb9bFrlzrok7fvr0Kfv727dvWRmdVTJHw0qiiCUSZ6wCK+7XL/AcsgNyL74DQQ730sv78Su7+t/A36MdY0sW5o40ahslXr58aZ5HtZB8GH64m9EmMZ7FpYw4T6QnrZfgenrhFxaSiSGXtPnz57e9TkNZLvTjeqhr734CNtrK41L40sUQckmj1lGKQ0rC37x544r8eNXRpnVE3ZZY7zXo8NomiO0ZUCj2uHz58rbXoZ6gc0uA+F6ZeKS/jhRDUq8MKrTho9fEkihMmhxtBI1DxKFY9XLpVcSkfoi8JGnToZO5sU5aiDQIW716ddt7ZLYtMQlhECdBGXZZMWldY5BHm5xgAroWj4C0hbYkSc/jBmggIrXJWlZM6pSETsEPGqZOndr2uuuR5rF169a2HoHPdurUKZM4CO1WTPqaDaAd+GFGKdIQkxAn9RuEWcTRyN2KSUgiSgF5aWzPTeA/lN5rZubMmR2bE4SIC4nJoltgAV/dVefZm72AtctUCJU2CMJ327hxY9t7EHbkyJFseq+EJSY16RPo3Dkq1kkr7+q0bNmyDuLQcZBEPYmHVdOBiJyIlrRDq41YPWfXOxUysi5fvtyaj+2BpcnsUV/oSoEMOk2CQGlr4ckhBwaetBhjCwH0ZHtJROPJkyc7UjcYLDjmrH7ADTEBXFfOYmB0k9oYBOjJ8b4aOYSe7QkKcYhFlq3QYLQhSidNmtS2RATwy8YOM3EQJsUjKiaWZ+vZToUQgzhkHXudb/PW5YMHD9yZM2faPsMwoc7RciYJXbGuBqJ1UIGKKLv915jsvgtJxCZDubdXr165mzdvtr1Hz5LONA8jrUwKPqsmVesKa49S3Q4WxmRPUEYdTjgiUcfUwLx589ySJUva3oMkP6IYddq6HMS4o55xBJBUeRjzfa4Zdeg56QZ43LhxoyPo7Lf1kNt7oO8wWAbNwaYjIv5lhyS7kRf96dvm5Jah8vfvX3flyhX35cuX6HfzFHOToS1H4BenCaHvO8pr8iDuwoUL7tevX+b5ZdbBair0xkFIlFDlW4ZknEClsp/TzXyAKVOmmHWFVSbDNw1l1+4f90U6IY/q4V27dpnE9bJ+v87QEydjqx/UamVVPRG+mwkNTYN+9tjkwzEx+atCm/X9WvWtDtAb68Wy9LXa1UmvCDDIpPkyOQ5ZwSzJ4jMrvFcr0rSjOUh+GcT4LSg5ugkW1Io0/SCDQBojh0hPlaJdah+tkVYrnTZowP8iq1F1TgMBBauufyB33x1v+NWFYmT5KmppgHC+NkAgbmRkpD3yn9QIseXymoTQFGQmIOKTxiZIWpvAatenVqRVXf2nTrAWMsPnKrMZHz6bJq5jvce6QK8J1cQNgKxlJapMPdZSR64/UivS9NztpkVEdKcrs5alhhWP9NeqlfWopzhZScI6QxseegZRGeg5a8C3Re1Mfl1ScP36ddcUaMuv24iOJtz7sbUjTS4qBvKmstYJoUauiuD3k5qhyr7QdUHMeCgLa1Ear9NquemdXgmum4fvJ6w1lqsuDhNrg1qSpleJK7K3TF0Q2jSd94uSZ60kK1e3qyVpQK6PVWXp2/FC3mp6jBhKKOiY2h3gtUV64TWM6wDETRPLDfSakXmH3w8g9Jlug8ZtTt4kVF0kLUYYmCCtD/DrQ5YhMGbA9L3ucdjh0y8kOHW5gU/VEEmJTcL4Pz/f7mgoAbYkAAAAAElFTkSuQmCC", - }, - ], - }, - ], -}) - -const completion = await openai.completions.create({ - model: "llama3", - prompt: "Say this is a test.", -}) - -const listCompletion = await openai.models.list() - -const model = await openai.models.retrieve("llama3") - -const embedding = await openai.embeddings.create({ - model: "all-minilm", - input: ["why is the sky blue?", "why is the grass green?"], -}) -``` - -### `curl` - -``` shell -curl http://localhost:11434/v1/chat/completions \ - -H "Content-Type: application/json" \ - -d '{ - "model": "llama3", - "messages": [ - { - "role": "system", - "content": "You are a helpful assistant." - }, - { - "role": "user", - "content": "Hello!" - } - ] - }' - -curl http://localhost:11434/v1/chat/completions \ - -H "Content-Type: application/json" \ - -d '{ - "model": "llava", - "messages": [ - { - "role": "user", - "content": [ - { - "type": "text", - "text": "What'\''s in this image?" - }, - { - "type": "image_url", - "image_url": { - "url": "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" - } - } - ] - } - ], - "max_tokens": 300 - }' - -curl http://localhost:11434/v1/completions \ - -H "Content-Type: application/json" \ - -d '{ - "model": "llama3", - "prompt": "Say this is a test" - }' - -curl http://localhost:11434/v1/models - -curl http://localhost:11434/v1/models/llama3 - -curl http://localhost:11434/v1/embeddings \ - -H "Content-Type: application/json" \ - -d '{ - "model": "all-minilm", - "input": ["why is the sky blue?", "why is the grass green?"] - }' -``` - -## Endpoints - -### `/v1/chat/completions` - -#### Supported features - -- [x] Chat completions -- [x] Streaming -- [x] JSON mode -- [x] Reproducible outputs -- [x] Vision -- [x] Tools (streaming support coming soon) -- [ ] Vision -- [ ] Logprobs - -#### Supported request fields - -- [x] `model` -- [x] `messages` - - [x] Text `content` - - [x] Image `content` - - [x] Base64 encoded image - - [ ] Image URL - - [x] Array of `content` parts -- [x] `frequency_penalty` -- [x] `presence_penalty` -- [x] `response_format` -- [x] `seed` -- [x] `stop` -- [x] `stream` -- [x] `temperature` -- [x] `top_p` -- [x] `max_tokens` -- [x] `tools` -- [ ] `tool_choice` -- [ ] `logit_bias` -- [ ] `user` -- [ ] `n` - -### `/v1/completions` - -#### Supported features - -- [x] Completions -- [x] Streaming -- [x] JSON mode -- [x] Reproducible outputs -- [ ] Logprobs - -#### Supported request fields - -- [x] `model` -- [x] `prompt` -- [x] `frequency_penalty` -- [x] `presence_penalty` -- [x] `seed` -- [x] `stop` -- [x] `stream` -- [x] `temperature` -- [x] `top_p` -- [x] `max_tokens` -- [x] `suffix` -- [ ] `best_of` -- [ ] `echo` -- [ ] `logit_bias` -- [ ] `user` -- [ ] `n` - -#### Notes - -- `prompt` currently only accepts a string - -### `/v1/models` - -#### Notes - -- `created` corresponds to when the model was last modified -- `owned_by` corresponds to the ollama username, defaulting to `"library"` - -### `/v1/models/{model}` - -#### Notes - -- `created` corresponds to when the model was last modified -- `owned_by` corresponds to the ollama username, defaulting to `"library"` - -### `/v1/embeddings` - -#### Supported request fields - -- [x] `model` -- [x] `input` - - [x] string - - [x] array of strings - - [ ] array of tokens - - [ ] array of token arrays -- [ ] `encoding format` -- [ ] `dimensions` -- [ ] `user` - -## Models - -Before using a model, pull it locally `ollama pull`: - -```shell -ollama pull llama3 -``` - -### Default model names - -For tooling that relies on default OpenAI model names such as `gpt-3.5-turbo`, use `ollama cp` to copy an existing model name to a temporary name: - -``` -ollama cp llama3 gpt-3.5-turbo -``` - -Afterwards, this new model name can be specified the `model` field: - -```shell -curl http://localhost:11434/v1/chat/completions \ - -H "Content-Type: application/json" \ - -d '{ - "model": "gpt-3.5-turbo", - "messages": [ - { - "role": "user", - "content": "Hello!" - } - ] - }' -``` diff --git a/ollama/docs/template.md b/ollama/docs/template.md deleted file mode 100755 index f6ce06b..0000000 --- a/ollama/docs/template.md +++ /dev/null @@ -1,173 +0,0 @@ -# Template - -Ollama provides a powerful templating engine backed by Go's built-in templating engine to construct prompts for your large language model. This feature is a valuable tool to get the most out of your models. - -## Basic Template Structure - -A basic Go template consists of three main parts: - -* **Layout**: The overall structure of the template. -* **Variables**: Placeholders for dynamic data that will be replaced with actual values when the template is rendered. -* **Functions**: Custom functions or logic that can be used to manipulate the template's content. - -Here's an example of a simple chat template: - -```gotmpl -{{- range .Messages }} -{{ .Role }}: {{ .Content }} -{{- end }} -``` - -In this example, we have: - -* A basic messages structure (layout) -* Three variables: `Messages`, `Role`, and `Content` (variables) -* A custom function (action) that iterates over an array of items (`range .Messages`) and displays each item - -## Adding templates to your model - -By default, models imported into Ollama have a default template of `{{ .Prompt }}`, i.e. user inputs are sent verbatim to the LLM. This is appropriate for text or code completion models but lacks essential markers for chat or instruction models. - -Omitting a template in these models puts the responsibility of correctly templating input onto the user. Adding a template allows users to easily get the best results from the model. - -To add templates in your model, you'll need to add a `TEMPLATE` command to the Modelfile. Here's an example using Meta's Llama 3. - -```dockerfile -FROM llama3 - -TEMPLATE """{{- if .System }}<|start_header_id|>system<|end_header_id|> - -{{ .System }}<|eot_id|> -{{- end }} -{{- range .Messages }}<|start_header_id|>{{ .Role }}<|end_header_id|> - -{{ .Content }}<|eot_id|> -{{- end }}<|start_header_id|>assistant<|end_header_id|> - -""" -``` - -## Variables - -`System` (string): system prompt - -`Prompt` (string): user prompt - -`Response` (string): assistant response - -`Suffix` (string): text inserted after the assistant's response - -`Messages` (list): list of messages - -`Messages[].Role` (string): role which can be one of `system`, `user`, `assistant`, or `tool` - -`Messages[].Content` (string): message content - -`Messages[].ToolCalls` (list): list of tools the model wants to call - -`Messages[].ToolCalls[].Function` (object): function to call - -`Messages[].ToolCalls[].Function.Name` (string): function name - -`Messages[].ToolCalls[].Function.Arguments` (map): mapping of argument name to argument value - -`Tools` (list): list of tools the model can access - -`Tools[].Type` (string): schema type. `type` is always `function` - -`Tools[].Function` (object): function definition - -`Tools[].Function.Name` (string): function name - -`Tools[].Function.Description` (string): function description - -`Tools[].Function.Parameters` (object): function parameters - -`Tools[].Function.Parameters.Type` (string): schema type. `type` is always `object` - -`Tools[].Function.Parameters.Required` (list): list of required properties - -`Tools[].Function.Parameters.Properties` (map): mapping of property name to property definition - -`Tools[].Function.Parameters.Properties[].Type` (string): property type - -`Tools[].Function.Parameters.Properties[].Description` (string): property description - -`Tools[].Function.Parameters.Properties[].Enum` (list): list of valid values - -## Tips and Best Practices - -Keep the following tips and best practices in mind when working with Go templates: - -* **Be mindful of dot**: Control flow structures like `range` and `with` changes the value `.` -* **Out-of-scope variables**: Use `$.` to reference variables not currently in scope, starting from the root -* **Whitespace control**: Use `-` to trim leading (`{{-`) and trailing (`-}}`) whitespace - -## Examples - -### Example Messages - -#### ChatML - -ChatML is a popular template format. It can be used for models such as Databrick's DBRX, Intel's Neural Chat, and Microsoft's Orca 2. - -```gotmpl -{{- if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }} -{{- range .Messages }}<|im_start|>{{ .Role }} -{{ .Content }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ else }} -{{ if .System }}<|im_start|>system -{{ .System }}<|im_end|> -``` - -### Example Tools - -Tools support can be added to a model by adding a `{{ .Tools }}` node to the template. This feature is useful for models trained to call external tools and can a powerful tool for retrieving real-time data or performing complex tasks. - -#### Mistral - -Mistral v0.3 and Mixtral 8x22B supports tool calling. - -```gotmpl -{{- range $index, $_ := .Messages }} -{{- if eq .Role "user" }} -{{- if and (le (len (slice $.Messages $index)) 2) $.Tools }}[AVAILABLE_TOOLS] {{ json $.Tools }}[/AVAILABLE_TOOLS] -{{- end }}[INST] {{ if and (eq (len (slice $.Messages $index)) 1) $.System }}{{ $.System }} - -{{ end }}{{ .Content }}[/INST] -{{- else if eq .Role "assistant" }} -{{- if .Content }} {{ .Content }} -{{- else if .ToolCalls }}[TOOL_CALLS] [ -{{- range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ json .Function.Arguments }}} -{{- end }}] -{{- end }} -{{- else if eq .Role "tool" }}[TOOL_RESULTS] {"content": {{ .Content }}}[/TOOL_RESULTS] -{{- end }} -{{- end }} -``` - -### Example Fill-in-Middle - -Fill-in-middle support can be added to a model by adding a `{{ .Suffix }}` node to the template. This feature is useful for models that are trained to generate text in the middle of user input, such as code completion models. - -#### CodeLlama - -CodeLlama [7B](https://ollama.com/library/codellama:7b-code) and [13B](https://ollama.com/library/codellama:13b-code) code completion models support fill-in-middle. - -```gotmpl -
 {{ .Prompt }} {{ .Suffix }} 
-```
-
-> [!NOTE]
-> CodeLlama 34B and 70B code completion and all instruct and Python fine-tuned models do not support fill-in-middle.
-
-#### Codestral
-
-Codestral [22B](https://ollama.com/library/codestral:22b) supports fill-in-middle.
-
-```gotmpl
-[SUFFIX]{{ .Suffix }}[PREFIX] {{ .Prompt }}
-```
diff --git a/ollama/docs/troubleshooting.md b/ollama/docs/troubleshooting.md
deleted file mode 100755
index 589061a..0000000
--- a/ollama/docs/troubleshooting.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# How to troubleshoot issues
-
-Sometimes Ollama may not perform as expected. One of the best ways to figure out what happened is to take a look at the logs. Find the logs on **Mac** by running the command:
-
-```shell
-cat ~/.ollama/logs/server.log
-```
-
-On **Linux** systems with systemd, the logs can be found with this command:
-
-```shell
-journalctl -u ollama --no-pager
-```
-
-When you run Ollama in a **container**, the logs go to stdout/stderr in the container:
-
-```shell
-docker logs 
-```
-(Use `docker ps` to find the container name)
-
-If manually running `ollama serve` in a terminal, the logs will be on that terminal.
-
-When you run Ollama on **Windows**, there are a few different locations. You can view them in the explorer window by hitting `+R` and type in:
-- `explorer %LOCALAPPDATA%\Ollama` to view logs.  The most recent server logs will be in `server.log` and older logs will be in `server-#.log` 
-- `explorer %LOCALAPPDATA%\Programs\Ollama` to browse the binaries (The installer adds this to your user PATH)
-- `explorer %HOMEPATH%\.ollama` to browse where models and configuration is stored
-- `explorer %TEMP%` where temporary executable files are stored in one or more `ollama*` directories
-
-To enable additional debug logging to help troubleshoot problems, first **Quit the running app from the tray menu** then in a powershell terminal
-```powershell
-$env:OLLAMA_DEBUG="1"
-& "ollama app.exe"
-```
-
-Join the [Discord](https://discord.gg/ollama) for help interpreting the logs.
-
-## LLM libraries
-
-Ollama includes multiple LLM libraries compiled for different GPUs and CPU vector features. Ollama tries to pick the best one based on the capabilities of your system. If this autodetection has problems, or you run into other problems (e.g. crashes in your GPU) you can workaround this by forcing a specific LLM library. `cpu_avx2` will perform the best, followed by `cpu_avx` an the slowest but most compatible is `cpu`. Rosetta emulation under MacOS will work with the `cpu` library. 
-
-In the server log, you will see a message that looks something like this (varies from release to release):
-
-```
-Dynamic LLM libraries [rocm_v6 cpu cpu_avx cpu_avx2 cuda_v11 rocm_v5]
-```
-
-**Experimental LLM Library Override**
-
-You can set OLLAMA_LLM_LIBRARY to any of the available LLM libraries to bypass autodetection, so for example, if you have a CUDA card, but want to force the CPU LLM library with AVX2 vector support, use:
-
-```
-OLLAMA_LLM_LIBRARY="cpu_avx2" ollama serve
-```
-
-You can see what features your CPU has with the following.
-```
-cat /proc/cpuinfo| grep flags | head -1
-```
-
-## Installing older or pre-release versions on Linux
-
-If you run into problems on Linux and want to install an older version, or you'd like to try out a pre-release before it's officially released, you can tell the install script which version to install.
-
-```sh
-curl -fsSL https://ollama.com/install.sh | OLLAMA_VERSION="0.1.29" sh
-```
-
-## Linux tmp noexec 
-
-If your system is configured with the "noexec" flag where Ollama stores its temporary executable files, you can specify an alternate location by setting OLLAMA_TMPDIR to a location writable by the user ollama runs as. For example OLLAMA_TMPDIR=/usr/share/ollama/
-
-## NVIDIA GPU Discovery
-
-When Ollama starts up, it takes inventory of the GPUs present in the system to determine compatibility and how much VRAM is available.  Sometimes this discovery can fail to find your GPUs.  In general, running the latest driver will yield the best results.
-
-### Linux NVIDIA Troubleshooting
-
-If you are using a container to run Ollama, make sure you've set up the container runtime first as described in [docker.md](./docker.md)
-
-Sometimes the Ollama can have difficulties initializing the GPU. When you check the server logs, this can show up as various error codes, such as "3" (not initialized), "46" (device unavailable), "100" (no device), "999" (unknown), or others. The following troubleshooting techniques may help resolve the problem
-
-- If you are using a container, is the container runtime working?  Try `docker run --gpus all ubuntu nvidia-smi` - if this doesn't work, Ollama wont be able to see your NVIDIA GPU.
-- Is the uvm driver loaded? `sudo nvidia-modprobe -u`
-- Try reloading the nvidia_uvm driver - `sudo rmmod nvidia_uvm` then `sudo modprobe nvidia_uvm`
-- Try rebooting
-- Make sure you're running the latest nvidia drivers
-
-If none of those resolve the problem, gather additional information and file an issue:
-- Set `CUDA_ERROR_LEVEL=50` and try again to get more diagnostic logs
-- Check dmesg for any errors `sudo dmesg | grep -i nvrm` and `sudo dmesg | grep -i nvidia`
-
-
-## Windows Terminal Errors
-
-Older versions of Windows 10 (e.g., 21H1) are known to have a bug where the standard terminal program does not display control characters correctly.  This can result in a long string of strings like `←[?25h←[?25l` being displayed, sometimes erroring with `The parameter is incorrect`  To resolve this problem, please update to Win 10 22H1 or newer.
diff --git a/ollama/docs/tutorials.md b/ollama/docs/tutorials.md
deleted file mode 100755
index 0f520c9..0000000
--- a/ollama/docs/tutorials.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Tutorials
-
-Here is a list of ways you can use Ollama with other tools to build interesting applications.
-
-- [Using LangChain with Ollama in JavaScript](./tutorials/langchainjs.md)
-- [Using LangChain with Ollama in Python](./tutorials/langchainpy.md)
-- [Running Ollama on NVIDIA Jetson Devices](./tutorials/nvidia-jetson.md)
-
-Also be sure to check out the [examples](../examples) directory for more ways to use Ollama.
diff --git a/ollama/docs/tutorials/fly-gpu.md b/ollama/docs/tutorials/fly-gpu.md
deleted file mode 100755
index 24802dd..0000000
--- a/ollama/docs/tutorials/fly-gpu.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Running Ollama on Fly.io GPU Instances
-
-Ollama runs with little to no configuration on [Fly.io GPU instances](https://fly.io/docs/gpus/gpu-quickstart/). If you don't have access to GPUs yet, you'll need to [apply for access](https://fly.io/gpu/) on the waitlist. Once you're accepted, you'll get an email with instructions on how to get started.
-
-Create a new app with `fly apps create`:
-
-```bash
-fly apps create
-```
-
-Then create a `fly.toml` file in a new folder that looks like this:
-
-```toml
-app = "sparkling-violet-709"
-primary_region = "ord"
-vm.size = "a100-40gb" # see https://fly.io/docs/gpus/gpu-quickstart/ for more info
-
-[build]
-  image = "ollama/ollama"
-
-[http_service]
-  internal_port = 11434
-  force_https = false
-  auto_stop_machines = true
-  auto_start_machines = true
-  min_machines_running = 0
-  processes = ["app"]
-
-[mounts]
-  source = "models"
-  destination = "/root/.ollama"
-  initial_size = "100gb"
-```
-
-Then create a [new private IPv6 address](https://fly.io/docs/reference/private-networking/#flycast-private-load-balancing) for your app:
-
-```bash
-fly ips allocate-v6 --private
-```
-
-Then deploy your app:
-
-```bash
-fly deploy
-```
-
-And finally you can access it interactively with a new Fly.io Machine:
-
-```
-fly machine run -e OLLAMA_HOST=http://your-app-name.flycast --shell ollama/ollama
-```
-
-```bash
-$ ollama run openchat:7b-v3.5-fp16
->>> How do I bake chocolate chip cookies?
- To bake chocolate chip cookies, follow these steps:
-
-1. Preheat the oven to 375°F (190°C) and line a baking sheet with parchment paper or silicone baking mat.
-
-2. In a large bowl, mix together 1 cup of unsalted butter (softened), 3/4 cup granulated sugar, and 3/4
-cup packed brown sugar until light and fluffy.
-
-3. Add 2 large eggs, one at a time, to the butter mixture, beating well after each addition. Stir in 1
-teaspoon of pure vanilla extract.
-
-4. In a separate bowl, whisk together 2 cups all-purpose flour, 1/2 teaspoon baking soda, and 1/2 teaspoon
-salt. Gradually add the dry ingredients to the wet ingredients, stirring until just combined.
-
-5. Fold in 2 cups of chocolate chips (or chunks) into the dough.
-
-6. Drop rounded tablespoons of dough onto the prepared baking sheet, spacing them about 2 inches apart.
-
-7. Bake for 10-12 minutes, or until the edges are golden brown. The centers should still be slightly soft.
-
-8. Allow the cookies to cool on the baking sheet for a few minutes before transferring them to a wire rack
-to cool completely.
-
-Enjoy your homemade chocolate chip cookies!
-```
-
-When you set it up like this, it will automatically turn off when you're done using it. Then when you access it again, it will automatically turn back on. This is a great way to save money on GPU instances when you're not using them. If you want a persistent wake-on-use connection to your Ollama instance, you can set up a [connection to your Fly network using WireGuard](https://fly.io/docs/reference/private-networking/#discovering-apps-through-dns-on-a-wireguard-connection). Then you can access your Ollama instance at `http://your-app-name.flycast`.
-
-And that's it!
diff --git a/ollama/docs/tutorials/langchainjs.md b/ollama/docs/tutorials/langchainjs.md
deleted file mode 100755
index f925869..0000000
--- a/ollama/docs/tutorials/langchainjs.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Using LangChain with Ollama using JavaScript
-
-In this tutorial, we are going to use JavaScript with LangChain and Ollama to learn about something just a touch more recent. In August 2023, there was a series of wildfires on Maui. There is no way an LLM trained before that time can know about this, since their training data would not include anything as recent as that. So we can find the [Wikipedia article about the fires](https://en.wikipedia.org/wiki/2023_Hawaii_wildfires) and ask questions about the contents.
-
-To get started, let's just use **LangChain** to ask a simple question to a model. To do this with JavaScript, we need to install **LangChain**:
-
-```bash
-npm install @langchain/community
-```
-
-Now we can start building out our JavaScript:
-
-```javascript
-import { Ollama } from "@langchain/community/llms/ollama";
-
-const ollama = new Ollama({
-  baseUrl: "http://localhost:11434",
-  model: "llama3.1",
-});
-
-const answer = await ollama.invoke(`why is the sky blue?`);
-
-console.log(answer);
-```
-
-That will get us the same thing as if we ran `ollama run llama3.1 "why is the sky blue"` in the terminal. But we want to load a document from the web to ask a question against. **Cheerio** is a great library for ingesting a webpage, and **LangChain** uses it in their **CheerioWebBaseLoader**. So let's install **Cheerio** and build that part of the app.
-
-```bash
-npm install cheerio
-```
-
-```javascript
-import { CheerioWebBaseLoader } from "langchain/document_loaders/web/cheerio";
-
-const loader = new CheerioWebBaseLoader("https://en.wikipedia.org/wiki/2023_Hawaii_wildfires");
-const data = await loader.load();
-```
-
-That will load the document. Although this page is smaller than the Odyssey, it is certainly bigger than the context size for most LLMs. So we are going to need to split into smaller pieces, and then select just the pieces relevant to our question. This is a great use for a vector datastore. In this example, we will use the **MemoryVectorStore** that is part of **LangChain**. But there is one more thing we need to get the content into the datastore. We have to run an embeddings process that converts the tokens in the text into a series of vectors. And for that, we are going to use **Tensorflow**. There is a lot of stuff going on in this one. First, install the **Tensorflow** components that we need.
-
-```javascript
-npm install @tensorflow/tfjs-core@3.6.0 @tensorflow/tfjs-converter@3.6.0 @tensorflow-models/universal-sentence-encoder@1.3.3 @tensorflow/tfjs-node@4.10.0
-```
-
-If you just install those components without the version numbers, it will install the latest versions, but there are conflicts within **Tensorflow**, so you need to install the compatible versions.
-
-```javascript
-import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"
-import { MemoryVectorStore } from "langchain/vectorstores/memory";
-import "@tensorflow/tfjs-node";
-import { TensorFlowEmbeddings } from "langchain/embeddings/tensorflow";
-
-// Split the text into 500 character chunks. And overlap each chunk by 20 characters
-const textSplitter = new RecursiveCharacterTextSplitter({
- chunkSize: 500,
- chunkOverlap: 20
-});
-const splitDocs = await textSplitter.splitDocuments(data);
-
-// Then use the TensorFlow Embedding to store these chunks in the datastore
-const vectorStore = await MemoryVectorStore.fromDocuments(splitDocs, new TensorFlowEmbeddings());
-```
-
-To connect the datastore to a question asked to a LLM, we need to use the concept at the heart of **LangChain**: the chain. Chains are a way to connect a number of activities together to accomplish a particular tasks. There are a number of chain types available, but for this tutorial we are using the **RetrievalQAChain**.
-
-```javascript
-import { RetrievalQAChain } from "langchain/chains";
-
-const retriever = vectorStore.asRetriever();
-const chain = RetrievalQAChain.fromLLM(ollama, retriever);
-const result = await chain.call({query: "When was Hawaii's request for a major disaster declaration approved?"});
-console.log(result.text)
-```
-
-So we created a retriever, which is a way to return the chunks that match a query from a datastore. And then connect the retriever and the model via a chain. Finally, we send a query to the chain, which results in an answer using our document as a source. The answer it returned was correct, August 10, 2023.
-
-And that is a simple introduction to what you can do with **LangChain** and **Ollama.**
diff --git a/ollama/docs/tutorials/langchainpy.md b/ollama/docs/tutorials/langchainpy.md
deleted file mode 100755
index 06543a0..0000000
--- a/ollama/docs/tutorials/langchainpy.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Using LangChain with Ollama in Python
-
-Let's imagine we are studying the classics, such as **the Odyssey** by **Homer**. We might have a question about Neleus and his family. If you ask llama2 for that info, you may get something like:
-
-> I apologize, but I'm a large language model, I cannot provide information on individuals or families that do not exist in reality. Neleus is not a real person or character, and therefore does not have a family or any other personal details. My apologies for any confusion. Is there anything else I can help you with?
-
-This sounds like a typical censored response, but even llama2-uncensored gives a mediocre answer:
-
-> Neleus was a legendary king of Pylos and the father of Nestor, one of the Argonauts. His mother was Clymene, a sea nymph, while his father was Neptune, the god of the sea.
-
-So let's figure out how we can use **LangChain** with Ollama to ask our question to the actual document, the Odyssey by Homer, using Python.
-
-Let's start by asking a simple question that we can get an answer to from the **Llama2** model using **Ollama**. First, we need to install the **LangChain** package:
-
-`pip install langchain_community`
-
-Then we can create a model and ask the question:
-
-```python
-from langchain_community.llms import Ollama
-ollama = Ollama(
-    base_url='http://localhost:11434',
-    model="llama3"
-)
-print(ollama.invoke("why is the sky blue"))
-```
-
-Notice that we are defining the model and the base URL for Ollama.
-
-Now let's load a document to ask questions against. I'll load up the Odyssey by Homer, which you can find at Project Gutenberg. We will need **WebBaseLoader** which is part of **LangChain** and loads text from any webpage. On my machine, I also needed to install **bs4** to get that to work, so run `pip install bs4`.
-
-```python
-from langchain.document_loaders import WebBaseLoader
-loader = WebBaseLoader("https://www.gutenberg.org/files/1727/1727-h/1727-h.htm")
-data = loader.load()
-```
-
-This file is pretty big. Just the preface is 3000 tokens. Which means the full document won't fit into the context for the model. So we need to split it up into smaller pieces.
-
-```python
-from langchain.text_splitter import RecursiveCharacterTextSplitter
-
-text_splitter=RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
-all_splits = text_splitter.split_documents(data)
-```
-
-It's split up, but we have to find the relevant splits and then submit those to the model. We can do this by creating embeddings and storing them in a vector database. We can use Ollama directly to instantiate an embedding model. We will use ChromaDB in this example for a vector database. `pip install chromadb`
-We also need to pull embedding model: `ollama pull nomic-embed-text`
-```python
-from langchain.embeddings import OllamaEmbeddings
-from langchain.vectorstores import Chroma
-oembed = OllamaEmbeddings(base_url="http://localhost:11434", model="nomic-embed-text")
-vectorstore = Chroma.from_documents(documents=all_splits, embedding=oembed)
-```
-
-Now let's ask a question from the document. **Who was Neleus, and who is in his family?** Neleus is a character in the Odyssey, and the answer can be found in our text.
-
-```python
-question="Who is Neleus and who is in Neleus' family?"
-docs = vectorstore.similarity_search(question)
-len(docs)
-```
-
-This will output the number of matches for chunks of data similar to the search.
-
-The next thing is to send the question and the relevant parts of the docs to the model to see if we can get a good answer. But we are stitching two parts of the process together, and that is called a chain. This means we need to define a chain:
-
-```python
-from langchain.chains import RetrievalQA
-qachain=RetrievalQA.from_chain_type(ollama, retriever=vectorstore.as_retriever())
-res = qachain.invoke({"query": question})
-print(res['result'])
-```
-
-The answer received from this chain was:
-
-> Neleus is a character in Homer's "Odyssey" and is mentioned in the context of Penelope's suitors. Neleus is the father of Chloris, who is married to Neleus and bears him several children, including Nestor, Chromius, Periclymenus, and Pero. Amphinomus, the son of Nisus, is also mentioned as a suitor of Penelope and is known for his good natural disposition and agreeable conversation.
-
-It's not a perfect answer, as it implies Neleus married his daughter when actually Chloris "was the youngest daughter to Amphion son of Iasus and king of Minyan Orchomenus, and was Queen in Pylos".
-
-I updated the chunk_overlap for the text splitter to 20 and tried again and got a much better answer:
-
-> Neleus is a character in Homer's epic poem "The Odyssey." He is the husband of Chloris, who is the youngest daughter of Amphion son of Iasus and king of Minyan Orchomenus. Neleus has several children with Chloris, including Nestor, Chromius, Periclymenus, and Pero.
-
-And that is a much better answer.
diff --git a/ollama/docs/tutorials/nvidia-jetson.md b/ollama/docs/tutorials/nvidia-jetson.md
deleted file mode 100755
index bb77c48..0000000
--- a/ollama/docs/tutorials/nvidia-jetson.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Running Ollama on NVIDIA Jetson Devices
-
-Ollama runs well on [NVIDIA Jetson Devices](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/) and should run out of the box with the standard installation instructions. 
-
-The following has been tested on [JetPack 5.1.2](https://developer.nvidia.com/embedded/jetpack), but should also work on JetPack 6.0.
-
-- Install Ollama via standard Linux command (ignore the 404 error): `curl https://ollama.com/install.sh | sh`
-- Pull the model you want to use (e.g. mistral): `ollama pull mistral`
-- Start an interactive session: `ollama run mistral`
-
-And that's it!
-
-# Running Ollama in Docker
-
-When running GPU accelerated applications in Docker, it is highly recommended to use [dusty-nv jetson-containers repo](https://github.com/dusty-nv/jetson-containers).
\ No newline at end of file
diff --git a/ollama/docs/windows.md b/ollama/docs/windows.md
deleted file mode 100755
index dbfc144..0000000
--- a/ollama/docs/windows.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Ollama Windows Preview
-
-Welcome to the Ollama Windows preview.
-
-No more WSL required!
-
-Ollama now runs as a native Windows application, including NVIDIA and AMD Radeon GPU support.
-After installing Ollama Windows Preview, Ollama will run in the background and
-the `ollama` command line is available in `cmd`, `powershell` or your favorite
-terminal application. As usual the Ollama [api](./api.md) will be served on
-`http://localhost:11434`.
-
-As this is a preview release, you should expect a few bugs here and there.  If
-you run into a problem you can reach out on
-[Discord](https://discord.gg/ollama), or file an
-[issue](https://github.com/ollama/ollama/issues).
-Logs will often be helpful in diagnosing the problem (see
-[Troubleshooting](#troubleshooting) below)
-
-## System Requirements
-
-* Windows 10 22H2 or newer, Home or Pro
-* NVIDIA 452.39 or newer Drivers if you have an NVIDIA card
-* AMD Radeon Driver https://www.amd.com/en/support if you have a Radeon card
-
-Ollama uses unicode characters for progress indication, which may render as unknown squares in some older terminal fonts in Windows 10. If you see this, try changing your terminal font settings.
-
-## API Access
-
-Here's a quick example showing API access from `powershell`
-```powershell
-(Invoke-WebRequest -method POST -Body '{"model":"llama3", "prompt":"Why is the sky blue?", "stream": false}' -uri http://localhost:11434/api/generate ).Content | ConvertFrom-json
-```
-
-## Troubleshooting
-
-While we're in preview, `OLLAMA_DEBUG` is always enabled, which adds
-a "view logs" menu item to the app, and increases logging for the GUI app and
-server.
-
-Ollama on Windows stores files in a few different locations.  You can view them in
-the explorer window by hitting `+R` and type in:
-- `explorer %LOCALAPPDATA%\Ollama` contains logs, and downloaded updates
-    - *app.log* contains most resent logs from the GUI application
-    - *server.log* contains the most recent server logs
-    - *upgrade.log* contains log output for upgrades
-- `explorer %LOCALAPPDATA%\Programs\Ollama` contains the binaries (The installer adds this to your user PATH)
-- `explorer %HOMEPATH%\.ollama` contains models and configuration
-- `explorer %TEMP%` contains temporary executable files in one or more `ollama*` directories
-
-
-## Standalone CLI
-
-The easiest way to install Ollama on Windows is to use the `OllamaSetup.exe`
-installer. It installs in your account without requiring Administrator rights.
-We update Ollama regularly to support the latest models, and this installer will
-help you keep up to date.
-
-If you'd like to install or integrate Ollama as a service, a standalone
-`ollama-windows-amd64.zip` zip file is available containing only the Ollama CLI
-and GPU library dependencies for Nvidia and AMD. This allows for embedding
-Ollama in existing applications, or running it as a system service via `ollama
-serve` with tools such as [NSSM](https://nssm.cc/).
diff --git a/ollama/envconfig/config.go b/ollama/envconfig/config.go
deleted file mode 100755
index b82b773..0000000
--- a/ollama/envconfig/config.go
+++ /dev/null
@@ -1,284 +0,0 @@
-package envconfig
-
-import (
-	"fmt"
-	"log/slog"
-	"math"
-	"net"
-	"net/url"
-	"os"
-	"path/filepath"
-	"runtime"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Host returns the scheme and host. Host can be configured via the OLLAMA_HOST environment variable.
-// Default is scheme "http" and host "127.0.0.1:11434"
-func Host() *url.URL {
-	defaultPort := "11434"
-
-	s := strings.TrimSpace(Var("OLLAMA_HOST"))
-	scheme, hostport, ok := strings.Cut(s, "://")
-	switch {
-	case !ok:
-		scheme, hostport = "http", s
-	case scheme == "http":
-		defaultPort = "80"
-	case scheme == "https":
-		defaultPort = "443"
-	}
-
-	// trim trailing slashes
-	hostport = strings.TrimRight(hostport, "/")
-
-	host, port, err := net.SplitHostPort(hostport)
-	if err != nil {
-		host, port = "127.0.0.1", defaultPort
-		if ip := net.ParseIP(strings.Trim(hostport, "[]")); ip != nil {
-			host = ip.String()
-		} else if hostport != "" {
-			host = hostport
-		}
-	}
-
-	if n, err := strconv.ParseInt(port, 10, 32); err != nil || n > 65535 || n < 0 {
-		slog.Warn("invalid port, using default", "port", port, "default", defaultPort)
-		return &url.URL{
-			Scheme: scheme,
-			Host:   net.JoinHostPort(host, defaultPort),
-		}
-	}
-
-	return &url.URL{
-		Scheme: scheme,
-		Host:   net.JoinHostPort(host, port),
-	}
-}
-
-// Origins returns a list of allowed origins. Origins can be configured via the OLLAMA_ORIGINS environment variable.
-func Origins() (origins []string) {
-	if s := Var("OLLAMA_ORIGINS"); s != "" {
-		origins = strings.Split(s, ",")
-	}
-
-	for _, origin := range []string{"localhost", "127.0.0.1", "0.0.0.0"} {
-		origins = append(origins,
-			fmt.Sprintf("http://%s", origin),
-			fmt.Sprintf("https://%s", origin),
-			fmt.Sprintf("http://%s", net.JoinHostPort(origin, "*")),
-			fmt.Sprintf("https://%s", net.JoinHostPort(origin, "*")),
-		)
-	}
-
-	origins = append(origins,
-		"app://*",
-		"file://*",
-		"tauri://*",
-	)
-
-	return origins
-}
-
-// Models returns the path to the models directory. Models directory can be configured via the OLLAMA_MODELS environment variable.
-// Default is $HOME/.ollama/models
-func Models() string {
-	if s := Var("OLLAMA_MODELS"); s != "" {
-		return s
-	}
-
-	home, err := os.UserHomeDir()
-	if err != nil {
-		panic(err)
-	}
-
-	return filepath.Join(home, ".ollama", "models")
-}
-
-// KeepAlive returns the duration that models stay loaded in memory. KeepAlive can be configured via the OLLAMA_KEEP_ALIVE environment variable.
-// Negative values are treated as infinite. Zero is treated as no keep alive.
-// Default is 5 minutes.
-func KeepAlive() (keepAlive time.Duration) {
-	keepAlive = 5 * time.Minute
-	if s := Var("OLLAMA_KEEP_ALIVE"); s != "" {
-		if d, err := time.ParseDuration(s); err == nil {
-			keepAlive = d
-		} else if n, err := strconv.ParseInt(s, 10, 64); err == nil {
-			keepAlive = time.Duration(n) * time.Second
-		}
-	}
-
-	if keepAlive < 0 {
-		return time.Duration(math.MaxInt64)
-	}
-
-	return keepAlive
-}
-
-func Bool(k string) func() bool {
-	return func() bool {
-		if s := Var(k); s != "" {
-			b, err := strconv.ParseBool(s)
-			if err != nil {
-				return true
-			}
-
-			return b
-		}
-
-		return false
-	}
-}
-
-var (
-	// Debug enabled additional debug information.
-	Debug = Bool("OLLAMA_DEBUG")
-	// FlashAttention enables the experimental flash attention feature.
-	FlashAttention = Bool("OLLAMA_FLASH_ATTENTION")
-	// NoHistory disables readline history.
-	NoHistory = Bool("OLLAMA_NOHISTORY")
-	// NoPrune disables pruning of model blobs on startup.
-	NoPrune = Bool("OLLAMA_NOPRUNE")
-	// SchedSpread allows scheduling models across all GPUs.
-	SchedSpread = Bool("OLLAMA_SCHED_SPREAD")
-	// IntelGPU enables experimental Intel GPU detection.
-	IntelGPU = Bool("OLLAMA_INTEL_GPU")
-)
-
-func String(s string) func() string {
-	return func() string {
-		return Var(s)
-	}
-}
-
-var (
-	LLMLibrary = String("OLLAMA_LLM_LIBRARY")
-	TmpDir     = String("OLLAMA_TMPDIR")
-
-	CudaVisibleDevices    = String("CUDA_VISIBLE_DEVICES")
-	HipVisibleDevices     = String("HIP_VISIBLE_DEVICES")
-	RocrVisibleDevices    = String("ROCR_VISIBLE_DEVICES")
-	GpuDeviceOrdinal      = String("GPU_DEVICE_ORDINAL")
-	HsaOverrideGfxVersion = String("HSA_OVERRIDE_GFX_VERSION")
-)
-
-func RunnersDir() (p string) {
-	if p := Var("OLLAMA_RUNNERS_DIR"); p != "" {
-		return p
-	}
-
-	if runtime.GOOS != "windows" {
-		return
-	}
-
-	defer func() {
-		if p == "" {
-			slog.Error("unable to locate llm runner directory. Set OLLAMA_RUNNERS_DIR to the location of 'ollama_runners'")
-		}
-	}()
-
-	// On Windows we do not carry the payloads inside the main executable
-	exe, err := os.Executable()
-	if err != nil {
-		return
-	}
-
-	cwd, err := os.Getwd()
-	if err != nil {
-		return
-	}
-
-	var paths []string
-	for _, root := range []string{filepath.Dir(exe), cwd} {
-		paths = append(paths,
-			root,
-			filepath.Join(root, "windows-"+runtime.GOARCH),
-			filepath.Join(root, "dist", "windows-"+runtime.GOARCH),
-		)
-	}
-
-	// Try a few variations to improve developer experience when building from source in the local tree
-	for _, path := range paths {
-		candidate := filepath.Join(path, "ollama_runners")
-		if _, err := os.Stat(candidate); err == nil {
-			p = candidate
-			break
-		}
-	}
-
-	return p
-}
-
-func Uint(key string, defaultValue uint) func() uint {
-	return func() uint {
-		if s := Var(key); s != "" {
-			if n, err := strconv.ParseUint(s, 10, 64); err != nil {
-				slog.Warn("invalid environment variable, using default", "key", key, "value", s, "default", defaultValue)
-			} else {
-				return uint(n)
-			}
-		}
-
-		return defaultValue
-	}
-}
-
-var (
-	// NumParallel sets the number of parallel model requests. NumParallel can be configured via the OLLAMA_NUM_PARALLEL environment variable.
-	NumParallel = Uint("OLLAMA_NUM_PARALLEL", 0)
-	// MaxRunners sets the maximum number of loaded models. MaxRunners can be configured via the OLLAMA_MAX_LOADED_MODELS environment variable.
-	MaxRunners = Uint("OLLAMA_MAX_LOADED_MODELS", 0)
-	// MaxQueue sets the maximum number of queued requests. MaxQueue can be configured via the OLLAMA_MAX_QUEUE environment variable.
-	MaxQueue = Uint("OLLAMA_MAX_QUEUE", 512)
-	// MaxVRAM sets a maximum VRAM override in bytes. MaxVRAM can be configured via the OLLAMA_MAX_VRAM environment variable.
-	MaxVRAM = Uint("OLLAMA_MAX_VRAM", 0)
-)
-
-type EnvVar struct {
-	Name        string
-	Value       any
-	Description string
-}
-
-func AsMap() map[string]EnvVar {
-	ret := map[string]EnvVar{
-		"OLLAMA_DEBUG":             {"OLLAMA_DEBUG", Debug(), "Show additional debug information (e.g. OLLAMA_DEBUG=1)"},
-		"OLLAMA_FLASH_ATTENTION":   {"OLLAMA_FLASH_ATTENTION", FlashAttention(), "Enabled flash attention"},
-		"OLLAMA_HOST":              {"OLLAMA_HOST", Host(), "IP Address for the ollama server (default 127.0.0.1:11434)"},
-		"OLLAMA_KEEP_ALIVE":        {"OLLAMA_KEEP_ALIVE", KeepAlive(), "The duration that models stay loaded in memory (default \"5m\")"},
-		"OLLAMA_LLM_LIBRARY":       {"OLLAMA_LLM_LIBRARY", LLMLibrary(), "Set LLM library to bypass autodetection"},
-		"OLLAMA_MAX_LOADED_MODELS": {"OLLAMA_MAX_LOADED_MODELS", MaxRunners(), "Maximum number of loaded models per GPU"},
-		"OLLAMA_MAX_QUEUE":         {"OLLAMA_MAX_QUEUE", MaxQueue(), "Maximum number of queued requests"},
-		"OLLAMA_MODELS":            {"OLLAMA_MODELS", Models(), "The path to the models directory"},
-		"OLLAMA_NOHISTORY":         {"OLLAMA_NOHISTORY", NoHistory(), "Do not preserve readline history"},
-		"OLLAMA_NOPRUNE":           {"OLLAMA_NOPRUNE", NoPrune(), "Do not prune model blobs on startup"},
-		"OLLAMA_NUM_PARALLEL":      {"OLLAMA_NUM_PARALLEL", NumParallel(), "Maximum number of parallel requests"},
-		"OLLAMA_ORIGINS":           {"OLLAMA_ORIGINS", Origins(), "A comma separated list of allowed origins"},
-		"OLLAMA_RUNNERS_DIR":       {"OLLAMA_RUNNERS_DIR", RunnersDir(), "Location for runners"},
-		"OLLAMA_SCHED_SPREAD":      {"OLLAMA_SCHED_SPREAD", SchedSpread(), "Always schedule model across all GPUs"},
-		"OLLAMA_TMPDIR":            {"OLLAMA_TMPDIR", TmpDir(), "Location for temporary files"},
-	}
-	if runtime.GOOS != "darwin" {
-		ret["CUDA_VISIBLE_DEVICES"] = EnvVar{"CUDA_VISIBLE_DEVICES", CudaVisibleDevices(), "Set which NVIDIA devices are visible"}
-		ret["HIP_VISIBLE_DEVICES"] = EnvVar{"HIP_VISIBLE_DEVICES", HipVisibleDevices(), "Set which AMD devices are visible"}
-		ret["ROCR_VISIBLE_DEVICES"] = EnvVar{"ROCR_VISIBLE_DEVICES", RocrVisibleDevices(), "Set which AMD devices are visible"}
-		ret["GPU_DEVICE_ORDINAL"] = EnvVar{"GPU_DEVICE_ORDINAL", GpuDeviceOrdinal(), "Set which AMD devices are visible"}
-		ret["HSA_OVERRIDE_GFX_VERSION"] = EnvVar{"HSA_OVERRIDE_GFX_VERSION", HsaOverrideGfxVersion(), "Override the gfx used for all detected AMD GPUs"}
-		ret["OLLAMA_INTEL_GPU"] = EnvVar{"OLLAMA_INTEL_GPU", IntelGPU(), "Enable experimental Intel GPU detection"}
-	}
-	return ret
-}
-
-func Values() map[string]string {
-	vals := make(map[string]string)
-	for k, v := range AsMap() {
-		vals[k] = fmt.Sprintf("%v", v.Value)
-	}
-	return vals
-}
-
-// Var returns an environment variable stripped of leading and trailing quotes or spaces
-func Var(key string) string {
-	return strings.Trim(strings.TrimSpace(os.Getenv(key)), "\"'")
-}
diff --git a/ollama/envconfig/config_test.go b/ollama/envconfig/config_test.go
deleted file mode 100755
index 92a500f..0000000
--- a/ollama/envconfig/config_test.go
+++ /dev/null
@@ -1,235 +0,0 @@
-package envconfig
-
-import (
-	"math"
-	"testing"
-	"time"
-
-	"github.com/google/go-cmp/cmp"
-)
-
-func TestHost(t *testing.T) {
-	cases := map[string]struct {
-		value  string
-		expect string
-	}{
-		"empty":               {"", "127.0.0.1:11434"},
-		"only address":        {"1.2.3.4", "1.2.3.4:11434"},
-		"only port":           {":1234", ":1234"},
-		"address and port":    {"1.2.3.4:1234", "1.2.3.4:1234"},
-		"hostname":            {"example.com", "example.com:11434"},
-		"hostname and port":   {"example.com:1234", "example.com:1234"},
-		"zero port":           {":0", ":0"},
-		"too large port":      {":66000", ":11434"},
-		"too small port":      {":-1", ":11434"},
-		"ipv6 localhost":      {"[::1]", "[::1]:11434"},
-		"ipv6 world open":     {"[::]", "[::]:11434"},
-		"ipv6 no brackets":    {"::1", "[::1]:11434"},
-		"ipv6 + port":         {"[::1]:1337", "[::1]:1337"},
-		"extra space":         {" 1.2.3.4 ", "1.2.3.4:11434"},
-		"extra quotes":        {"\"1.2.3.4\"", "1.2.3.4:11434"},
-		"extra space+quotes":  {" \" 1.2.3.4 \" ", "1.2.3.4:11434"},
-		"extra single quotes": {"'1.2.3.4'", "1.2.3.4:11434"},
-		"http":                {"http://1.2.3.4", "1.2.3.4:80"},
-		"http port":           {"http://1.2.3.4:4321", "1.2.3.4:4321"},
-		"https":               {"https://1.2.3.4", "1.2.3.4:443"},
-		"https port":          {"https://1.2.3.4:4321", "1.2.3.4:4321"},
-	}
-
-	for name, tt := range cases {
-		t.Run(name, func(t *testing.T) {
-			t.Setenv("OLLAMA_HOST", tt.value)
-			if host := Host(); host.Host != tt.expect {
-				t.Errorf("%s: expected %s, got %s", name, tt.expect, host.Host)
-			}
-		})
-	}
-}
-
-func TestOrigins(t *testing.T) {
-	cases := []struct {
-		value  string
-		expect []string
-	}{
-		{"", []string{
-			"http://localhost",
-			"https://localhost",
-			"http://localhost:*",
-			"https://localhost:*",
-			"http://127.0.0.1",
-			"https://127.0.0.1",
-			"http://127.0.0.1:*",
-			"https://127.0.0.1:*",
-			"http://0.0.0.0",
-			"https://0.0.0.0",
-			"http://0.0.0.0:*",
-			"https://0.0.0.0:*",
-			"app://*",
-			"file://*",
-			"tauri://*",
-		}},
-		{"http://10.0.0.1", []string{
-			"http://10.0.0.1",
-			"http://localhost",
-			"https://localhost",
-			"http://localhost:*",
-			"https://localhost:*",
-			"http://127.0.0.1",
-			"https://127.0.0.1",
-			"http://127.0.0.1:*",
-			"https://127.0.0.1:*",
-			"http://0.0.0.0",
-			"https://0.0.0.0",
-			"http://0.0.0.0:*",
-			"https://0.0.0.0:*",
-			"app://*",
-			"file://*",
-			"tauri://*",
-		}},
-		{"http://172.16.0.1,https://192.168.0.1", []string{
-			"http://172.16.0.1",
-			"https://192.168.0.1",
-			"http://localhost",
-			"https://localhost",
-			"http://localhost:*",
-			"https://localhost:*",
-			"http://127.0.0.1",
-			"https://127.0.0.1",
-			"http://127.0.0.1:*",
-			"https://127.0.0.1:*",
-			"http://0.0.0.0",
-			"https://0.0.0.0",
-			"http://0.0.0.0:*",
-			"https://0.0.0.0:*",
-			"app://*",
-			"file://*",
-			"tauri://*",
-		}},
-		{"http://totally.safe,http://definitely.legit", []string{
-			"http://totally.safe",
-			"http://definitely.legit",
-			"http://localhost",
-			"https://localhost",
-			"http://localhost:*",
-			"https://localhost:*",
-			"http://127.0.0.1",
-			"https://127.0.0.1",
-			"http://127.0.0.1:*",
-			"https://127.0.0.1:*",
-			"http://0.0.0.0",
-			"https://0.0.0.0",
-			"http://0.0.0.0:*",
-			"https://0.0.0.0:*",
-			"app://*",
-			"file://*",
-			"tauri://*",
-		}},
-	}
-	for _, tt := range cases {
-		t.Run(tt.value, func(t *testing.T) {
-			t.Setenv("OLLAMA_ORIGINS", tt.value)
-
-			if diff := cmp.Diff(Origins(), tt.expect); diff != "" {
-				t.Errorf("%s: mismatch (-want +got):\n%s", tt.value, diff)
-			}
-		})
-	}
-}
-
-func TestBool(t *testing.T) {
-	cases := map[string]bool{
-		"":      false,
-		"true":  true,
-		"false": false,
-		"1":     true,
-		"0":     false,
-		// invalid values
-		"random":    true,
-		"something": true,
-	}
-
-	for k, v := range cases {
-		t.Run(k, func(t *testing.T) {
-			t.Setenv("OLLAMA_BOOL", k)
-			if b := Bool("OLLAMA_BOOL")(); b != v {
-				t.Errorf("%s: expected %t, got %t", k, v, b)
-			}
-		})
-	}
-}
-
-func TestUint(t *testing.T) {
-	cases := map[string]uint{
-		"0":    0,
-		"1":    1,
-		"1337": 1337,
-		// default values
-		"":       11434,
-		"-1":     11434,
-		"0o10":   11434,
-		"0x10":   11434,
-		"string": 11434,
-	}
-
-	for k, v := range cases {
-		t.Run(k, func(t *testing.T) {
-			t.Setenv("OLLAMA_UINT", k)
-			if i := Uint("OLLAMA_UINT", 11434)(); i != v {
-				t.Errorf("%s: expected %d, got %d", k, v, i)
-			}
-		})
-	}
-}
-
-func TestKeepAlive(t *testing.T) {
-	cases := map[string]time.Duration{
-		"":       5 * time.Minute,
-		"1s":     time.Second,
-		"1m":     time.Minute,
-		"1h":     time.Hour,
-		"5m0s":   5 * time.Minute,
-		"1h2m3s": 1*time.Hour + 2*time.Minute + 3*time.Second,
-		"0":      time.Duration(0),
-		"60":     60 * time.Second,
-		"120":    2 * time.Minute,
-		"3600":   time.Hour,
-		"-0":     time.Duration(0),
-		"-1":     time.Duration(math.MaxInt64),
-		"-1m":    time.Duration(math.MaxInt64),
-		// invalid values
-		" ":   5 * time.Minute,
-		"???": 5 * time.Minute,
-		"1d":  5 * time.Minute,
-		"1y":  5 * time.Minute,
-		"1w":  5 * time.Minute,
-	}
-
-	for tt, expect := range cases {
-		t.Run(tt, func(t *testing.T) {
-			t.Setenv("OLLAMA_KEEP_ALIVE", tt)
-			if actual := KeepAlive(); actual != expect {
-				t.Errorf("%s: expected %s, got %s", tt, expect, actual)
-			}
-		})
-	}
-}
-
-func TestVar(t *testing.T) {
-	cases := map[string]string{
-		"value":       "value",
-		" value ":     "value",
-		" 'value' ":   "value",
-		` "value" `:   "value",
-		" ' value ' ": " value ",
-		` " value " `: " value ",
-	}
-
-	for k, v := range cases {
-		t.Run(k, func(t *testing.T) {
-			t.Setenv("OLLAMA_VAR", k)
-			if s := Var("OLLAMA_VAR"); s != v {
-				t.Errorf("%s: expected %q, got %q", k, v, s)
-			}
-		})
-	}
-}
diff --git a/ollama/examples/.gitignore b/ollama/examples/.gitignore
deleted file mode 100755
index b60652b..0000000
--- a/ollama/examples/.gitignore
+++ /dev/null
@@ -1,174 +0,0 @@
-node_modules
-bun.lockb
-.vscode
-# OSX
-.DS_STORE
-
-
-# Models
-models/
-
-# Local Chroma db
-.chroma/
-db/
-
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-#   For a library or package, you might want to ignore these files since the code is
-#   intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-#   However, in case of collaboration, if having platform-specific dependencies or dependencies
-#   having no cross-platform support, pipenv may install dependencies that don't work, or not
-#   install all needed dependencies.
-#Pipfile.lock
-
-# poetry
-#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
-#   This is especially recommended for binary packages to ensure reproducibility, and is more
-#   commonly ignored for libraries.
-#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
-#poetry.lock
-
-# pdm
-#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
-#pdm.lock
-#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
-#   in version control.
-#   https://pdm.fming.dev/#use-with-ide
-.pdm.toml
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
-
-# PyCharm
-#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
-#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
-#  and can be added to the global gitignore or merged into this file.  For a more nuclear
-#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
diff --git a/ollama/examples/README.md b/ollama/examples/README.md
deleted file mode 100755
index b10a349..0000000
--- a/ollama/examples/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Examples
-
-This directory contains different examples of using Ollama.
diff --git a/ollama/examples/flyio/.gitignore b/ollama/examples/flyio/.gitignore
deleted file mode 100755
index 0501d09..0000000
--- a/ollama/examples/flyio/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-fly.toml
diff --git a/ollama/examples/flyio/README.md b/ollama/examples/flyio/README.md
deleted file mode 100755
index 09b90aa..0000000
--- a/ollama/examples/flyio/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Deploy Ollama to Fly.io
-
-> Note: this example exposes a public endpoint and does not configure authentication. Use with care.
-
-## Prerequisites
-
-- Ollama: https://ollama.com/download
-- Fly.io account. Sign up for a free account: https://fly.io/app/sign-up
-
-## Steps
-
-1. Login to Fly.io
-
-    ```bash
-    fly auth login
-    ```
-
-1. Create a new Fly app
-
-    ```bash
-    fly launch --name  --image ollama/ollama --internal-port 11434 --vm-size shared-cpu-8x --now
-    ```
-
-1. Pull and run `orca-mini:3b`
-
-    ```bash
-    OLLAMA_HOST=https://.fly.dev ollama run orca-mini:3b
-    ```
-
-`shared-cpu-8x` is a free-tier eligible machine type. For better performance, switch to a `performance` or `dedicated` machine type or attach a GPU for hardware acceleration (see below).
-
-## (Optional) Persistent Volume
-
-By default Fly Machines use ephemeral storage which is problematic if you want to use the same model across restarts without pulling it again. Create and attach a persistent volume to store the downloaded models:
-
-1. Create the Fly Volume
-
-    ```bash
-    fly volume create ollama
-    ```
-
-1. Update `fly.toml` and add `[mounts]`
-
-    ```toml
-    [mounts]
-      source = "ollama"
-      destination = "/mnt/ollama/models"
-    ```
-
-1. Update `fly.toml` and add `[env]`
-
-    ```toml
-    [env]
-      OLLAMA_MODELS = "/mnt/ollama/models"
-    ```
-
-1. Deploy your app
-
-    ```bash
-    fly deploy
-    ```
-
-## (Optional) Hardware Acceleration
-
-Fly.io GPU is currently in waitlist. Sign up for the waitlist: https://fly.io/gpu
-
-Once you've been accepted, create the app with the additional flags `--vm-gpu-kind a100-pcie-40gb` or `--vm-gpu-kind a100-pcie-80gb`.
diff --git a/ollama/examples/go-chat/main.go b/ollama/examples/go-chat/main.go
deleted file mode 100755
index 7663fb8..0000000
--- a/ollama/examples/go-chat/main.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"log"
-
-	"github.com/ollama/ollama/api"
-)
-
-func main() {
-	client, err := api.ClientFromEnvironment()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	messages := []api.Message{
-		api.Message{
-			Role:    "system",
-			Content: "Provide very brief, concise responses",
-		},
-		api.Message{
-			Role:    "user",
-			Content: "Name some unusual animals",
-		},
-		api.Message{
-			Role:    "assistant",
-			Content: "Monotreme, platypus, echidna",
-		},
-		api.Message{
-			Role:    "user",
-			Content: "which of these is the most dangerous?",
-		},
-	}
-
-	ctx := context.Background()
-	req := &api.ChatRequest{
-		Model:    "llama3.1",
-		Messages: messages,
-	}
-
-	respFunc := func(resp api.ChatResponse) error {
-		fmt.Print(resp.Message.Content)
-		return nil
-	}
-
-	err = client.Chat(ctx, req, respFunc)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/ollama/examples/go-generate-streaming/main.go b/ollama/examples/go-generate-streaming/main.go
deleted file mode 100755
index 3acfb22..0000000
--- a/ollama/examples/go-generate-streaming/main.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"log"
-
-	"github.com/ollama/ollama/api"
-)
-
-func main() {
-	client, err := api.ClientFromEnvironment()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// By default, GenerateRequest is streaming.
-	req := &api.GenerateRequest{
-		Model:  "gemma2",
-		Prompt: "how many planets are there?",
-	}
-
-	ctx := context.Background()
-	respFunc := func(resp api.GenerateResponse) error {
-		// Only print the response here; GenerateResponse has a number of other
-		// interesting fields you want to examine.
-
-		// In streaming mode, responses are partial so we call fmt.Print (and not
-		// Println) in order to avoid spurious newlines being introduced. The
-		// model will insert its own newlines if it wants.
-		fmt.Print(resp.Response)
-		return nil
-	}
-
-	err = client.Generate(ctx, req, respFunc)
-	if err != nil {
-		log.Fatal(err)
-	}
-	fmt.Println()
-}
diff --git a/ollama/examples/go-generate/main.go b/ollama/examples/go-generate/main.go
deleted file mode 100755
index 2fe2874..0000000
--- a/ollama/examples/go-generate/main.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"log"
-
-	"github.com/ollama/ollama/api"
-)
-
-func main() {
-	client, err := api.ClientFromEnvironment()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	req := &api.GenerateRequest{
-		Model:  "gemma2",
-		Prompt: "how many planets are there?",
-
-		// set streaming to false
-		Stream: new(bool),
-	}
-
-	ctx := context.Background()
-	respFunc := func(resp api.GenerateResponse) error {
-		// Only print the response here; GenerateResponse has a number of other
-		// interesting fields you want to examine.
-		fmt.Println(resp.Response)
-		return nil
-	}
-
-	err = client.Generate(ctx, req, respFunc)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/ollama/examples/go-http-generate/main.go b/ollama/examples/go-http-generate/main.go
deleted file mode 100755
index e5b6434..0000000
--- a/ollama/examples/go-http-generate/main.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"net/http"
-	"os"
-)
-
-func main() {
-	body := []byte(`{"model":"mistral"}`)
-	resp, err := http.Post("http://localhost:11434/api/generate", "application/json", bytes.NewBuffer(body))
-
-	if err != nil {
-		fmt.Print(err.Error())
-		os.Exit(1)
-	}
-
-	defer resp.Body.Close()
-
-	responseData, err := io.ReadAll(resp.Body)
-	if err != nil {
-		log.Fatal(err)
-	}
-	fmt.Println(string(responseData))
-
-}
diff --git a/ollama/examples/go-multimodal/main.go b/ollama/examples/go-multimodal/main.go
deleted file mode 100755
index 0b0f19e..0000000
--- a/ollama/examples/go-multimodal/main.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"log"
-	"os"
-
-	"github.com/ollama/ollama/api"
-)
-
-func main() {
-	if len(os.Args) <= 1 {
-		log.Fatal("usage: ")
-	}
-
-	imgData, err := os.ReadFile(os.Args[1])
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	client, err := api.ClientFromEnvironment()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	req := &api.GenerateRequest{
-		Model:  "llava",
-		Prompt: "describe this image",
-		Images: []api.ImageData{imgData},
-	}
-
-	ctx := context.Background()
-	respFunc := func(resp api.GenerateResponse) error {
-		// In streaming mode, responses are partial so we call fmt.Print (and not
-		// Println) in order to avoid spurious newlines being introduced. The
-		// model will insert its own newlines if it wants.
-		fmt.Print(resp.Response)
-		return nil
-	}
-
-	err = client.Generate(ctx, req, respFunc)
-	if err != nil {
-		log.Fatal(err)
-	}
-	fmt.Println()
-}
diff --git a/ollama/examples/go-pull-progress/main.go b/ollama/examples/go-pull-progress/main.go
deleted file mode 100755
index 7486336..0000000
--- a/ollama/examples/go-pull-progress/main.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"log"
-
-	"github.com/ollama/ollama/api"
-)
-
-func main() {
-	client, err := api.ClientFromEnvironment()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	ctx := context.Background()
-
-	req := &api.PullRequest{
-		Model: "mistral",
-	}
-	progressFunc := func(resp api.ProgressResponse) error {
-		fmt.Printf("Progress: status=%v, total=%v, completed=%v\n", resp.Status, resp.Total, resp.Completed)
-		return nil
-	}
-
-	err = client.Pull(ctx, req, progressFunc)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/ollama/examples/jupyter-notebook/README.md b/ollama/examples/jupyter-notebook/README.md
deleted file mode 100755
index fba6802..0000000
--- a/ollama/examples/jupyter-notebook/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Ollama Jupyter Notebook
-
-This example downloads and installs Ollama in a Jupyter instance such as Google Colab. It will start the Ollama service and expose an endpoint using `ngrok` which can be used to communicate with the Ollama instance remotely.
-
-For best results, use an instance with GPU accelerator.
diff --git a/ollama/examples/jupyter-notebook/ollama.ipynb b/ollama/examples/jupyter-notebook/ollama.ipynb
deleted file mode 100755
index bee353c..0000000
--- a/ollama/examples/jupyter-notebook/ollama.ipynb
+++ /dev/null
@@ -1,102 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "93f59dcb-c588-41b8-a792-55d88ade739c",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# Download and run the Ollama Linux install script\n",
-    "!curl -fsSL https://ollama.com/install.sh | sh\n",
-    "!command -v systemctl >/dev/null && sudo systemctl stop ollama"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "658c147e-c7f8-490e-910e-62b80f577dda",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "!pip install aiohttp pyngrok\n",
-    "\n",
-    "import os\n",
-    "import asyncio\n",
-    "from aiohttp import ClientSession\n",
-    "\n",
-    "# Set LD_LIBRARY_PATH so the system NVIDIA library becomes preferred\n",
-    "# over the built-in library. This is particularly important for \n",
-    "# Google Colab which installs older drivers\n",
-    "os.environ.update({'LD_LIBRARY_PATH': '/usr/lib64-nvidia'})\n",
-    "\n",
-    "async def run(cmd):\n",
-    "  '''\n",
-    "  run is a helper function to run subcommands asynchronously.\n",
-    "  '''\n",
-    "  print('>>> starting', *cmd)\n",
-    "  p = await asyncio.subprocess.create_subprocess_exec(\n",
-    "      *cmd,\n",
-    "      stdout=asyncio.subprocess.PIPE,\n",
-    "      stderr=asyncio.subprocess.PIPE,\n",
-    "  )\n",
-    "\n",
-    "  async def pipe(lines):\n",
-    "    async for line in lines:\n",
-    "      print(line.strip().decode('utf-8'))\n",
-    "\n",
-    "  await asyncio.gather(\n",
-    "      pipe(p.stdout),\n",
-    "      pipe(p.stderr),\n",
-    "  )\n",
-    "\n",
-    "\n",
-    "await asyncio.gather(\n",
-    "    run(['ollama', 'serve']),\n",
-    "    run(['ngrok', 'http', '--log', 'stderr', '11434']),\n",
-    ")"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "e7735a55-9aad-4caf-8683-52e2163ba53b",
-   "metadata": {},
-   "source": [
-    "The previous cell starts two processes, `ollama` and `ngrok`. The log output will show a line like the following which describes the external address.\n",
-    "\n",
-    "```\n",
-    "t=2023-11-12T22:55:56+0000 lvl=info msg=\"started tunnel\" obj=tunnels name=command_line addr=http://localhost:11434 url=https://8249-34-125-179-11.ngrok.io\n",
-    "```\n",
-    "\n",
-    "The external address in this case is `https://8249-34-125-179-11.ngrok.io` which can be passed into `OLLAMA_HOST` to access this instance.\n",
-    "\n",
-    "```bash\n",
-    "export OLLAMA_HOST=https://8249-34-125-179-11.ngrok.io\n",
-    "ollama list\n",
-    "ollama run mistral\n",
-    "```"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3 (ipykernel)",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.11.6"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/ollama/examples/kubernetes/README.md b/ollama/examples/kubernetes/README.md
deleted file mode 100755
index 2e2444c..0000000
--- a/ollama/examples/kubernetes/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Deploy Ollama to Kubernetes
-
-## Prerequisites
-
-- Ollama: https://ollama.com/download
-- Kubernetes cluster. This example will use Google Kubernetes Engine.
-
-## Steps
-
-1. Create the Ollama namespace, deployment, and service
-
-   ```bash
-   kubectl apply -f cpu.yaml
-   ```
-
-## (Optional) Hardware Acceleration
-
-Hardware acceleration in Kubernetes requires NVIDIA's [`k8s-device-plugin`](https://github.com/NVIDIA/k8s-device-plugin) which is deployed in Kubernetes in form of daemonset. Follow the link for more details.
-
-Once configured, create a GPU enabled Ollama deployment.
-
-```bash
-kubectl apply -f gpu.yaml
-```
-
-## Test
-
-1. Port forward the Ollama service to connect and use it locally
-
-   ```bash
-   kubectl -n ollama port-forward service/ollama 11434:80
-   ```
-
-1. Pull and run a model, for example `orca-mini:3b`
-
-   ```bash
-   ollama run orca-mini:3b
-   ```
\ No newline at end of file
diff --git a/ollama/examples/kubernetes/cpu.yaml b/ollama/examples/kubernetes/cpu.yaml
deleted file mode 100755
index b8ddcdd..0000000
--- a/ollama/examples/kubernetes/cpu.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
----
-apiVersion: v1
-kind: Namespace
-metadata:
-  name: ollama
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: ollama
-  namespace: ollama
-spec:
-  selector:
-    matchLabels:
-      name: ollama
-  template:
-    metadata:
-      labels:
-        name: ollama
-    spec:
-      containers:
-      - name: ollama
-        image: ollama/ollama:latest
-        ports:
-        - name: http
-          containerPort: 11434
-          protocol: TCP
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: ollama
-  namespace: ollama
-spec:
-  type: ClusterIP
-  selector:
-    name: ollama
-  ports:
-  - port: 80
-    name: http
-    targetPort: http
-    protocol: TCP
diff --git a/ollama/examples/kubernetes/gpu.yaml b/ollama/examples/kubernetes/gpu.yaml
deleted file mode 100755
index ba90abb..0000000
--- a/ollama/examples/kubernetes/gpu.yaml
+++ /dev/null
@@ -1,58 +0,0 @@
----
-apiVersion: v1
-kind: Namespace
-metadata:
-  name: ollama
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: ollama
-  namespace: ollama
-spec:
-  strategy:
-    type: Recreate
-  selector:
-    matchLabels:
-      name: ollama
-  template:
-    metadata:
-      labels:
-        name: ollama
-    spec:
-      containers:
-      - name: ollama
-        image: ollama/ollama:latest
-        env:
-        - name: PATH
-          value: /usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-        - name: LD_LIBRARY_PATH
-          value: /usr/local/nvidia/lib:/usr/local/nvidia/lib64
-        - name: NVIDIA_DRIVER_CAPABILITIES
-          value: compute,utility
-        ports:
-        - name: http
-          containerPort: 11434
-          protocol: TCP
-        resources:
-          limits:
-            nvidia.com/gpu: 1
-      tolerations:
-      - key: nvidia.com/gpu
-        operator: Exists
-        effect: NoSchedule
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: ollama
-  namespace: ollama
-spec:
-  type: ClusterIP
-  selector:
-    name: ollama
-  ports:
-  - port: 80
-    name: http
-    targetPort: http
-    protocol: TCP
diff --git a/ollama/examples/langchain-python-rag-document/README.md b/ollama/examples/langchain-python-rag-document/README.md
deleted file mode 100755
index e2f3bc0..0000000
--- a/ollama/examples/langchain-python-rag-document/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# LangChain Document QA
-
-This example provides an interface for asking questions to a PDF document.
-
-## Setup
-
-1. Ensure you have the `llama3.1` model installed:
-
-```
-ollama pull llama3.1
-```
-
-2. Install the Python Requirements.
-
-```
-pip install -r requirements.txt
-```
-
-## Run
-
-```
-python main.py
-```
-
-A prompt will appear, where questions may be asked:
-
-```
-Query: How many locations does WeWork have?
-```
diff --git a/ollama/examples/langchain-python-rag-document/main.py b/ollama/examples/langchain-python-rag-document/main.py
deleted file mode 100755
index 6f7cec9..0000000
--- a/ollama/examples/langchain-python-rag-document/main.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from langchain.document_loaders import OnlinePDFLoader
-from langchain.vectorstores import Chroma
-from langchain.embeddings import GPT4AllEmbeddings
-from langchain import PromptTemplate
-from langchain.llms import Ollama
-from langchain.callbacks.manager import CallbackManager
-from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
-from langchain.chains import RetrievalQA
-import sys
-import os
-
-class SuppressStdout:
-    def __enter__(self):
-        self._original_stdout = sys.stdout
-        self._original_stderr = sys.stderr
-        sys.stdout = open(os.devnull, 'w')
-        sys.stderr = open(os.devnull, 'w')
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        sys.stdout.close()
-        sys.stdout = self._original_stdout
-        sys.stderr = self._original_stderr
-
-# load the pdf and split it into chunks
-loader = OnlinePDFLoader("https://d18rn0p25nwr6d.cloudfront.net/CIK-0001813756/975b3e9b-268e-4798-a9e4-2a9a7c92dc10.pdf")
-data = loader.load()
-
-from langchain.text_splitter import RecursiveCharacterTextSplitter
-text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
-all_splits = text_splitter.split_documents(data)
-
-with SuppressStdout():
-    vectorstore = Chroma.from_documents(documents=all_splits, embedding=GPT4AllEmbeddings())
-
-while True:
-    query = input("\nQuery: ")
-    if query == "exit":
-        break
-    if query.strip() == "":
-        continue
-
-    # Prompt
-    template = """Use the following pieces of context to answer the question at the end.
-    If you don't know the answer, just say that you don't know, don't try to make up an answer.
-    Use three sentences maximum and keep the answer as concise as possible.
-    {context}
-    Question: {question}
-    Helpful Answer:"""
-    QA_CHAIN_PROMPT = PromptTemplate(
-        input_variables=["context", "question"],
-        template=template,
-    )
-
-    llm = Ollama(model="llama3.1", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]))
-    qa_chain = RetrievalQA.from_chain_type(
-        llm,
-        retriever=vectorstore.as_retriever(),
-        chain_type_kwargs={"prompt": QA_CHAIN_PROMPT},
-    )
-
-    result = qa_chain({"query": query})
diff --git a/ollama/examples/langchain-python-rag-document/requirements.txt b/ollama/examples/langchain-python-rag-document/requirements.txt
deleted file mode 100755
index 09a5419..0000000
--- a/ollama/examples/langchain-python-rag-document/requirements.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-absl-py==1.4.0
-aiohttp==3.8.5
-aiosignal==1.3.1
-anyio==3.7.1
-astunparse==1.6.3
-async-timeout==4.0.3
-attrs==23.1.0
-backoff==2.2.1
-beautifulsoup4==4.12.2
-bs4==0.0.1
-cachetools==5.3.1
-certifi==2023.7.22
-cffi==1.15.1
-chardet==5.2.0
-charset-normalizer==3.2.0
-Chroma==0.2.0
-chroma-hnswlib==0.7.2
-chromadb==0.4.5
-click==8.1.6
-coloredlogs==15.0.1
-cryptography==41.0.3
-dataclasses-json==0.5.14
-fastapi==0.99.1
-filetype==1.2.0
-flatbuffers==23.5.26
-frozenlist==1.4.0
-gast==0.4.0
-google-auth==2.22.0
-google-auth-oauthlib==1.0.0
-google-pasta==0.2.0
-gpt4all==1.0.8
-grpcio==1.57.0
-h11==0.14.0
-h5py==3.9.0
-httptools==0.6.0
-humanfriendly==10.0
-idna==3.4
-importlib-resources==6.0.1
-joblib==1.3.2
-keras==2.13.1
-langchain==0.0.261
-langsmith==0.0.21
-libclang==16.0.6
-lxml==4.9.3
-Markdown==3.4.4
-MarkupSafe==2.1.3
-marshmallow==3.20.1
-monotonic==1.6
-mpmath==1.3.0
-multidict==6.0.4
-mypy-extensions==1.0.0
-nltk==3.8.1
-numexpr==2.8.5
-numpy==1.24.3
-oauthlib==3.2.2
-onnxruntime==1.15.1
-openapi-schema-pydantic==1.2.4
-opt-einsum==3.3.0
-overrides==7.4.0
-packaging==23.1
-pdf2image==1.16.3
-pdfminer==20191125
-pdfminer.six==20221105
-Pillow==10.0.0
-posthog==3.0.1
-protobuf==4.24.0
-pulsar-client==3.2.0
-pyasn1==0.5.0
-pyasn1-modules==0.3.0
-pycparser==2.21
-pycryptodome==3.18.0
-pydantic==1.10.12
-PyPika==0.48.9
-python-dateutil==2.8.2
-python-dotenv==1.0.0
-python-magic==0.4.27
-PyYAML==6.0.1
-regex==2023.8.8
-requests==2.31.0
-requests-oauthlib==1.3.1
-rsa==4.9
-six==1.16.0
-sniffio==1.3.0
-soupsieve==2.4.1
-SQLAlchemy==2.0.19
-starlette==0.27.0
-sympy==1.12
-tabulate==0.9.0
-tenacity==8.2.2
-tensorboard==2.13.0
-tensorboard-data-server==0.7.1
-tensorflow==2.13.0
-tensorflow-estimator==2.13.0
-tensorflow-hub==0.14.0
-tensorflow-macos==2.13.0
-termcolor==2.3.0
-tokenizers==0.13.3
-tqdm==4.66.1
-typing-inspect==0.9.0
-typing_extensions==4.5.0
-unstructured==0.9.2
-urllib3==1.26.16
-uvicorn==0.23.2
-uvloop==0.17.0
-watchfiles==0.19.0
-websockets==11.0.3
-Werkzeug==2.3.6
-wrapt==1.15.0
-yarl==1.9.2
diff --git a/ollama/examples/langchain-python-rag-privategpt/.gitignore b/ollama/examples/langchain-python-rag-privategpt/.gitignore
deleted file mode 100755
index 240b29e..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/.gitignore
+++ /dev/null
@@ -1,170 +0,0 @@
-# OSX
-.DS_STORE
-
-# Models
-models/
-
-# Local Chroma db
-.chroma/
-db/
-
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-#   For a library or package, you might want to ignore these files since the code is
-#   intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-#   However, in case of collaboration, if having platform-specific dependencies or dependencies
-#   having no cross-platform support, pipenv may install dependencies that don't work, or not
-#   install all needed dependencies.
-#Pipfile.lock
-
-# poetry
-#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
-#   This is especially recommended for binary packages to ensure reproducibility, and is more
-#   commonly ignored for libraries.
-#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
-#poetry.lock
-
-# pdm
-#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
-#pdm.lock
-#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
-#   in version control.
-#   https://pdm.fming.dev/#use-with-ide
-.pdm.toml
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
-
-# PyCharm
-#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
-#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
-#  and can be added to the global gitignore or merged into this file.  For a more nuclear
-#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
diff --git a/ollama/examples/langchain-python-rag-privategpt/LICENSE b/ollama/examples/langchain-python-rag-privategpt/LICENSE
deleted file mode 100755
index 261eeb9..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/ollama/examples/langchain-python-rag-privategpt/README.md b/ollama/examples/langchain-python-rag-privategpt/README.md
deleted file mode 100755
index 0133fd8..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# PrivateGPT with Llama 2 uncensored
-
-https://github.com/ollama/ollama/assets/3325447/20cf8ec6-ff25-42c6-bdd8-9be594e3ce1b
-
-> Note: this example is a slightly modified version of PrivateGPT using models such as Llama 2 Uncensored. All credit for PrivateGPT goes to Iván Martínez who is the creator of it, and you can find his GitHub repo [here](https://github.com/imartinez/privateGPT).
-
-### Setup
-
-Set up a virtual environment (optional):
-
-```
-python3 -m venv .venv
-source .venv/bin/activate
-```
-
-Install the Python dependencies:
-
-```shell
-pip install -r requirements.txt
-```
-
-Pull the model you'd like to use:
-
-```
-ollama pull llama2-uncensored
-```
-
-### Getting WeWork's latest quarterly earnings report (10-Q)
-
-```
-mkdir source_documents
-curl https://d18rn0p25nwr6d.cloudfront.net/CIK-0001813756/975b3e9b-268e-4798-a9e4-2a9a7c92dc10.pdf -o source_documents/wework.pdf
-```
-
-### Ingesting files
-
-```shell
-python ingest.py
-```
-
-Output should look like this:
-
-```shell
-Creating new vectorstore
-Loading documents from source_documents
-Loading new documents: 100%|██████████████████████| 1/1 [00:01<00:00,  1.73s/it]
-Loaded 1 new documents from source_documents
-Split into 90 chunks of text (max. 500 tokens each)
-Creating embeddings. May take some minutes...
-Using embedded DuckDB with persistence: data will be stored in: db
-Ingestion complete! You can now run privateGPT.py to query your documents
-```
-
-### Ask questions
-
-```shell
-python privateGPT.py
-
-Enter a query: How many locations does WeWork have?
-
-> Answer (took 17.7 s.):
-As of June 2023, WeWork has 777 locations worldwide, including 610 Consolidated Locations (as defined in the section entitled Key Performance Indicators).
-```
-
-### Try a different model:
-
-```
-ollama pull llama2:13b
-MODEL=llama2:13b python privateGPT.py
-```
-
-## Adding more files
-
-Put any and all your files into the `source_documents` directory
-
-The supported extensions are:
-
-- `.csv`: CSV,
-- `.docx`: Word Document,
-- `.doc`: Word Document,
-- `.enex`: EverNote,
-- `.eml`: Email,
-- `.epub`: EPub,
-- `.html`: HTML File,
-- `.md`: Markdown,
-- `.msg`: Outlook Message,
-- `.odt`: Open Document Text,
-- `.pdf`: Portable Document Format (PDF),
-- `.pptx` : PowerPoint Document,
-- `.ppt` : PowerPoint Document,
-- `.txt`: Text file (UTF-8),
diff --git a/ollama/examples/langchain-python-rag-privategpt/constants.py b/ollama/examples/langchain-python-rag-privategpt/constants.py
deleted file mode 100755
index 56dda79..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/constants.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import os
-from chromadb.config import Settings
-
-# Define the folder for storing database
-PERSIST_DIRECTORY = os.environ.get('PERSIST_DIRECTORY', 'db')
-
-# Define the Chroma settings
-CHROMA_SETTINGS = Settings(
-        persist_directory=PERSIST_DIRECTORY,
-        anonymized_telemetry=False
-)
diff --git a/ollama/examples/langchain-python-rag-privategpt/ingest.py b/ollama/examples/langchain-python-rag-privategpt/ingest.py
deleted file mode 100755
index 0f71ccf..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/ingest.py
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/env python3
-import os
-import glob
-from typing import List
-from multiprocessing import Pool
-from tqdm import tqdm
-
-from langchain.document_loaders import (
-    CSVLoader,
-    EverNoteLoader,
-    PyMuPDFLoader,
-    TextLoader,
-    UnstructuredEmailLoader,
-    UnstructuredEPubLoader,
-    UnstructuredHTMLLoader,
-    UnstructuredMarkdownLoader,
-    UnstructuredODTLoader,
-    UnstructuredPowerPointLoader,
-    UnstructuredWordDocumentLoader,
-)
-
-from langchain.text_splitter import RecursiveCharacterTextSplitter
-from langchain.vectorstores import Chroma
-from langchain.embeddings import HuggingFaceEmbeddings
-from langchain.docstore.document import Document
-from constants import CHROMA_SETTINGS
-
-
-# Load environment variables
-persist_directory = os.environ.get('PERSIST_DIRECTORY', 'db')
-source_directory = os.environ.get('SOURCE_DIRECTORY', 'source_documents')
-embeddings_model_name = os.environ.get('EMBEDDINGS_MODEL_NAME', 'all-MiniLM-L6-v2')
-chunk_size = 500
-chunk_overlap = 50
-
-# Custom document loaders
-class MyElmLoader(UnstructuredEmailLoader):
-    """Wrapper to fallback to text/plain when default does not work"""
-
-    def load(self) -> List[Document]:
-        """Wrapper adding fallback for elm without html"""
-        try:
-            try:
-                doc = UnstructuredEmailLoader.load(self)
-            except ValueError as e:
-                if 'text/html content not found in email' in str(e):
-                    # Try plain text
-                    self.unstructured_kwargs["content_source"]="text/plain"
-                    doc = UnstructuredEmailLoader.load(self)
-                else:
-                    raise
-        except Exception as e:
-            # Add file_path to exception message
-            raise type(e)(f"{self.file_path}: {e}") from e
-
-        return doc
-
-
-# Map file extensions to document loaders and their arguments
-LOADER_MAPPING = {
-    ".csv": (CSVLoader, {}),
-    # ".docx": (Docx2txtLoader, {}),
-    ".doc": (UnstructuredWordDocumentLoader, {}),
-    ".docx": (UnstructuredWordDocumentLoader, {}),
-    ".enex": (EverNoteLoader, {}),
-    ".eml": (MyElmLoader, {}),
-    ".epub": (UnstructuredEPubLoader, {}),
-    ".html": (UnstructuredHTMLLoader, {}),
-    ".md": (UnstructuredMarkdownLoader, {}),
-    ".odt": (UnstructuredODTLoader, {}),
-    ".pdf": (PyMuPDFLoader, {}),
-    ".ppt": (UnstructuredPowerPointLoader, {}),
-    ".pptx": (UnstructuredPowerPointLoader, {}),
-    ".txt": (TextLoader, {"encoding": "utf8"}),
-    # Add more mappings for other file extensions and loaders as needed
-}
-
-
-def load_single_document(file_path: str) -> List[Document]:
-    if os.path.getsize(file_path) != 0:
-        filename, ext = os.path.splitext(file_path)
-        if ext in LOADER_MAPPING:
-            loader_class, loader_args = LOADER_MAPPING[ext]
-            try:
-                loader = loader_class(file_path, **loader_args)
-                if loader:
-                    return loader.load()
-            except:
-                print(f"Corrupted file {file_path}. Ignoring it.")
-        else:
-            print(f"Unsupported file {file_path}. Ignoring it.")
-    else:
-        print(f"Empty file {file_path}. Ignoring it.")
-
-
-def load_documents(source_dir: str, ignored_files: List[str] = []) -> List[Document]:
-    """
-    Loads all documents from the source documents directory, ignoring specified files
-    """
-    all_files = []
-    for ext in LOADER_MAPPING:
-        all_files.extend(
-            glob.glob(os.path.join(source_dir, f"**/*{ext}"), recursive=True)
-        )
-    filtered_files = [file_path for file_path in all_files if file_path not in ignored_files]
-
-    with Pool(processes=os.cpu_count()) as pool:
-        results = []
-        with tqdm(total=len(filtered_files), desc='Loading new documents', ncols=80) as pbar:
-            for i, docs in enumerate(pool.imap_unordered(load_single_document, filtered_files)):
-                if docs:
-                    results.extend(docs)
-                pbar.update()
-
-    return results
-
-def process_documents(ignored_files: List[str] = []) -> List[Document]:
-    """
-    Load documents and split in chunks
-    """
-    print(f"Loading documents from {source_directory}")
-    documents = load_documents(source_directory, ignored_files)
-    if not documents:
-        print("No new documents to load")
-        exit(0)
-    print(f"Loaded {len(documents)} new documents from {source_directory}")
-    text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
-    texts = text_splitter.split_documents(documents)
-    print(f"Split into {len(texts)} chunks of text (max. {chunk_size} tokens each)")
-    return texts
-
-def does_vectorstore_exist(persist_directory: str) -> bool:
-    """
-    Checks if vectorstore exists
-    """
-    if os.path.exists(os.path.join(persist_directory, 'index')):
-        if os.path.exists(os.path.join(persist_directory, 'chroma-collections.parquet')) and os.path.exists(os.path.join(persist_directory, 'chroma-embeddings.parquet')):
-            list_index_files = glob.glob(os.path.join(persist_directory, 'index/*.bin'))
-            list_index_files += glob.glob(os.path.join(persist_directory, 'index/*.pkl'))
-            # At least 3 documents are needed in a working vectorstore
-            if len(list_index_files) > 3:
-                return True
-    return False
-
-def main():
-    # Create embeddings
-    embeddings = HuggingFaceEmbeddings(model_name=embeddings_model_name)
-
-    if does_vectorstore_exist(persist_directory):
-        # Update and store locally vectorstore
-        print(f"Appending to existing vectorstore at {persist_directory}")
-        db = Chroma(persist_directory=persist_directory, embedding_function=embeddings, client_settings=CHROMA_SETTINGS)
-        collection = db.get()
-        texts = process_documents([metadata['source'] for metadata in collection['metadatas']])
-        print(f"Creating embeddings. May take some minutes...")
-        db.add_documents(texts)
-    else:
-        # Create and store locally vectorstore
-        print("Creating new vectorstore")
-        texts = process_documents()
-        print(f"Creating embeddings. May take some minutes...")
-        db = Chroma.from_documents(texts, embeddings, persist_directory=persist_directory)
-    db.persist()
-    db = None
-
-    print(f"Ingestion complete! You can now run privateGPT.py to query your documents")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/ollama/examples/langchain-python-rag-privategpt/poetry.lock b/ollama/examples/langchain-python-rag-privategpt/poetry.lock
deleted file mode 100755
index f02b1c5..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/poetry.lock
+++ /dev/null
@@ -1,3833 +0,0 @@
-# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
-
-[[package]]
-name = "aiohttp"
-version = "3.8.4"
-description = "Async http client/server framework (asyncio)"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1"},
-    {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a"},
-    {file = "aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b"},
-    {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3"},
-    {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc"},
-    {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd"},
-    {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5"},
-    {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e"},
-    {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd"},
-    {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6"},
-    {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9"},
-    {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949"},
-    {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea"},
-    {file = "aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1"},
-    {file = "aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f"},
-    {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4"},
-    {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4"},
-    {file = "aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef"},
-    {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f"},
-    {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e"},
-    {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f"},
-    {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05"},
-    {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654"},
-    {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a"},
-    {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb"},
-    {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531"},
-    {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b"},
-    {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24"},
-    {file = "aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d"},
-    {file = "aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:880e15bb6dad90549b43f796b391cfffd7af373f4646784795e20d92606b7a51"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb96fa6b56bb536c42d6a4a87dfca570ff8e52de2d63cabebfd6fb67049c34b6"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a6cadebe132e90cefa77e45f2d2f1a4b2ce5c6b1bfc1656c1ddafcfe4ba8131"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f352b62b45dff37b55ddd7b9c0c8672c4dd2eb9c0f9c11d395075a84e2c40f75"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ab43061a0c81198d88f39aaf90dae9a7744620978f7ef3e3708339b8ed2ef01"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9cb1565a7ad52e096a6988e2ee0397f72fe056dadf75d17fa6b5aebaea05622"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1b3ea7edd2d24538959c1c1abf97c744d879d4e541d38305f9bd7d9b10c9ec41"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7c7837fe8037e96b6dd5cfcf47263c1620a9d332a87ec06a6ca4564e56bd0f36"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3b90467ebc3d9fa5b0f9b6489dfb2c304a1db7b9946fa92aa76a831b9d587e99"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:cab9401de3ea52b4b4c6971db5fb5c999bd4260898af972bf23de1c6b5dd9d71"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d1f9282c5f2b5e241034a009779e7b2a1aa045f667ff521e7948ea9b56e0c5ff"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-win32.whl", hash = "sha256:5e14f25765a578a0a634d5f0cd1e2c3f53964553a00347998dfdf96b8137f777"},
-    {file = "aiohttp-3.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4c745b109057e7e5f1848c689ee4fb3a016c8d4d92da52b312f8a509f83aa05e"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aede4df4eeb926c8fa70de46c340a1bc2c6079e1c40ccf7b0eae1313ffd33519"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddaae3f3d32fc2cb4c53fab020b69a05c8ab1f02e0e59665c6f7a0d3a5be54f"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4eb3b82ca349cf6fadcdc7abcc8b3a50ab74a62e9113ab7a8ebc268aad35bb9"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bcb89336efa095ea21b30f9e686763f2be4478f1b0a616969551982c4ee4c3b"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c08e8ed6fa3d477e501ec9db169bfac8140e830aa372d77e4a43084d8dd91ab"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6cd05ea06daca6ad6a4ca3ba7fe7dc5b5de063ff4daec6170ec0f9979f6c332"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7a00a9ed8d6e725b55ef98b1b35c88013245f35f68b1b12c5cd4100dddac333"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:de04b491d0e5007ee1b63a309956eaed959a49f5bb4e84b26c8f5d49de140fa9"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:40653609b3bf50611356e6b6554e3a331f6879fa7116f3959b20e3528783e699"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dbf3a08a06b3f433013c143ebd72c15cac33d2914b8ea4bea7ac2c23578815d6"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854f422ac44af92bfe172d8e73229c270dc09b96535e8a548f99c84f82dde241"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-win32.whl", hash = "sha256:aeb29c84bb53a84b1a81c6c09d24cf33bb8432cc5c39979021cc0f98c1292a1a"},
-    {file = "aiohttp-3.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:db3fc6120bce9f446d13b1b834ea5b15341ca9ff3f335e4a951a6ead31105480"},
-    {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fabb87dd8850ef0f7fe2b366d44b77d7e6fa2ea87861ab3844da99291e81e60f"},
-    {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91f6d540163f90bbaef9387e65f18f73ffd7c79f5225ac3d3f61df7b0d01ad15"},
-    {file = "aiohttp-3.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d265f09a75a79a788237d7f9054f929ced2e69eb0bb79de3798c468d8a90f945"},
-    {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d89efa095ca7d442a6d0cbc755f9e08190ba40069b235c9886a8763b03785da"},
-    {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dac314662f4e2aa5009977b652d9b8db7121b46c38f2073bfeed9f4049732cd"},
-    {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe11310ae1e4cd560035598c3f29d86cef39a83d244c7466f95c27ae04850f10"},
-    {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ddb2a2026c3f6a68c3998a6c47ab6795e4127315d2e35a09997da21865757f8"},
-    {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e75b89ac3bd27d2d043b234aa7b734c38ba1b0e43f07787130a0ecac1e12228a"},
-    {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6e601588f2b502c93c30cd5a45bfc665faaf37bbe835b7cfd461753068232074"},
-    {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a5d794d1ae64e7753e405ba58e08fcfa73e3fad93ef9b7e31112ef3c9a0efb52"},
-    {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a1f4689c9a1462f3df0a1f7e797791cd6b124ddbee2b570d34e7f38ade0e2c71"},
-    {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3032dcb1c35bc330134a5b8a5d4f68c1a87252dfc6e1262c65a7e30e62298275"},
-    {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8189c56eb0ddbb95bfadb8f60ea1b22fcfa659396ea36f6adcc521213cd7b44d"},
-    {file = "aiohttp-3.8.4-cp38-cp38-win32.whl", hash = "sha256:33587f26dcee66efb2fff3c177547bd0449ab7edf1b73a7f5dea1e38609a0c54"},
-    {file = "aiohttp-3.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:e595432ac259af2d4630008bf638873d69346372d38255774c0e286951e8b79f"},
-    {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a7bdf9e57126dc345b683c3632e8ba317c31d2a41acd5800c10640387d193ed"},
-    {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22f6eab15b6db242499a16de87939a342f5a950ad0abaf1532038e2ce7d31567"},
-    {file = "aiohttp-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7235604476a76ef249bd64cb8274ed24ccf6995c4a8b51a237005ee7a57e8643"},
-    {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9eb976ffdd79d0e893869cfe179a8f60f152d42cb64622fca418cd9b18dc2a"},
-    {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c0cea74a2a81c4c76b62ea1cac163ecb20fb3ba3a75c909b9fa71b4ad493cf"},
-    {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493f5bc2f8307286b7799c6d899d388bbaa7dfa6c4caf4f97ef7521b9cb13719"},
-    {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a63f03189a6fa7c900226e3ef5ba4d3bd047e18f445e69adbd65af433add5a2"},
-    {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10c8cefcff98fd9168cdd86c4da8b84baaa90bf2da2269c6161984e6737bf23e"},
-    {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bca5f24726e2919de94f047739d0a4fc01372801a3672708260546aa2601bf57"},
-    {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03baa76b730e4e15a45f81dfe29a8d910314143414e528737f8589ec60cf7391"},
-    {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8c29c77cc57e40f84acef9bfb904373a4e89a4e8b74e71aa8075c021ec9078c2"},
-    {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:03543dcf98a6619254b409be2d22b51f21ec66272be4ebda7b04e6412e4b2e14"},
-    {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17b79c2963db82086229012cff93ea55196ed31f6493bb1ccd2c62f1724324e4"},
-    {file = "aiohttp-3.8.4-cp39-cp39-win32.whl", hash = "sha256:34ce9f93a4a68d1272d26030655dd1b58ff727b3ed2a33d80ec433561b03d67a"},
-    {file = "aiohttp-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:41a86a69bb63bb2fc3dc9ad5ea9f10f1c9c8e282b471931be0268ddd09430b04"},
-    {file = "aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"},
-]
-
-[package.dependencies]
-aiosignal = ">=1.1.2"
-async-timeout = ">=4.0.0a3,<5.0"
-attrs = ">=17.3.0"
-charset-normalizer = ">=2.0,<4.0"
-frozenlist = ">=1.1.1"
-multidict = ">=4.5,<7.0"
-yarl = ">=1.0,<2.0"
-
-[package.extras]
-speedups = ["Brotli", "aiodns", "cchardet"]
-
-[[package]]
-name = "aiosignal"
-version = "1.3.1"
-description = "aiosignal: a list of registered asynchronous callbacks"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
-    {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
-]
-
-[package.dependencies]
-frozenlist = ">=1.1.0"
-
-[[package]]
-name = "anyio"
-version = "3.7.1"
-description = "High level compatibility layer for multiple asynchronous event loop implementations"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
-    {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
-]
-
-[package.dependencies]
-exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
-idna = ">=2.8"
-sniffio = ">=1.1"
-
-[package.extras]
-doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
-test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
-trio = ["trio (<0.22)"]
-
-[[package]]
-name = "argilla"
-version = "0.0.1"
-description = ""
-optional = false
-python-versions = "*"
-files = [
-    {file = "argilla-0.0.1-py3-none-any.whl", hash = "sha256:8bdc3c505bcfb47ba4b91f5658034eae53bf7d4f9317980397605c0c55817396"},
-    {file = "argilla-0.0.1.tar.gz", hash = "sha256:5017854754e89f573b31af25b25b803f51cea9ca1fa0bcf00505dee1f45cf7c9"},
-]
-
-[[package]]
-name = "async-timeout"
-version = "4.0.2"
-description = "Timeout context manager for asyncio programs"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
-    {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
-]
-
-[[package]]
-name = "attrs"
-version = "23.1.0"
-description = "Classes Without Boilerplate"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
-    {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
-]
-
-[package.extras]
-cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
-dev = ["attrs[docs,tests]", "pre-commit"]
-docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
-tests = ["attrs[tests-no-zope]", "zope-interface"]
-tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-
-[[package]]
-name = "backoff"
-version = "2.2.1"
-description = "Function decoration for backoff and retry"
-optional = false
-python-versions = ">=3.7,<4.0"
-files = [
-    {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"},
-    {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"},
-]
-
-[[package]]
-name = "beautifulsoup4"
-version = "4.12.2"
-description = "Screen-scraping library"
-optional = false
-python-versions = ">=3.6.0"
-files = [
-    {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"},
-    {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"},
-]
-
-[package.dependencies]
-soupsieve = ">1.2"
-
-[package.extras]
-html5lib = ["html5lib"]
-lxml = ["lxml"]
-
-[[package]]
-name = "certifi"
-version = "2023.5.7"
-description = "Python package for providing Mozilla's CA Bundle."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
-    {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
-]
-
-[[package]]
-name = "cffi"
-version = "1.15.1"
-description = "Foreign Function Interface for Python calling C code."
-optional = false
-python-versions = "*"
-files = [
-    {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
-    {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
-    {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
-    {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
-    {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
-    {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
-    {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
-    {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
-    {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
-    {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
-    {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
-    {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
-    {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
-    {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
-    {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
-    {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
-    {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
-    {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
-    {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
-    {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
-    {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
-    {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
-    {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
-    {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
-    {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
-    {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
-    {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
-    {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
-    {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
-    {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
-    {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
-    {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
-    {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
-    {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
-    {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
-    {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
-    {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
-    {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
-    {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
-    {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
-    {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
-    {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
-    {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
-    {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
-    {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
-    {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
-    {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
-    {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
-    {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
-    {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
-    {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
-    {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
-    {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
-    {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
-    {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
-    {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
-    {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
-    {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
-    {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
-    {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
-    {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
-    {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
-    {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
-    {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
-]
-
-[package.dependencies]
-pycparser = "*"
-
-[[package]]
-name = "chardet"
-version = "5.1.0"
-description = "Universal encoding detector for Python 3"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"},
-    {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"},
-]
-
-[[package]]
-name = "charset-normalizer"
-version = "3.2.0"
-description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-optional = false
-python-versions = ">=3.7.0"
-files = [
-    {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
-    {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
-    {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"},
-    {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"},
-    {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"},
-    {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"},
-    {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
-]
-
-[[package]]
-name = "chromadb"
-version = "0.3.26"
-description = "Chroma."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "chromadb-0.3.26-py3-none-any.whl", hash = "sha256:45a7848ee3ed8b694ca5789e5fd723406b76a13fa46f9a9a769f93317f29894c"},
-    {file = "chromadb-0.3.26.tar.gz", hash = "sha256:a9b596d507f081993f2e32a7dcacabbbec2f6aebc2b6defe524442b07e265296"},
-]
-
-[package.dependencies]
-clickhouse-connect = ">=0.5.7"
-duckdb = ">=0.7.1"
-fastapi = ">=0.85.1"
-hnswlib = ">=0.7"
-numpy = ">=1.21.6"
-onnxruntime = ">=1.14.1"
-overrides = ">=7.3.1"
-pandas = ">=1.3"
-posthog = ">=2.4.0"
-pulsar-client = ">=3.1.0"
-pydantic = ">=1.9"
-requests = ">=2.28"
-tokenizers = ">=0.13.2"
-tqdm = ">=4.65.0"
-typing-extensions = ">=4.5.0"
-uvicorn = {version = ">=0.18.3", extras = ["standard"]}
-
-[[package]]
-name = "click"
-version = "8.1.4"
-description = "Composable command line interface toolkit"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"},
-    {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-
-[[package]]
-name = "clickhouse-connect"
-version = "0.6.6"
-description = "ClickHouse Database Core Driver for Python, Pandas, and Superset"
-optional = false
-python-versions = "~=3.7"
-files = [
-    {file = "clickhouse-connect-0.6.6.tar.gz", hash = "sha256:28d261b95fe9818f4d8bc4ad48087cbff3c9f0b6574ff04d234ed5bca6619474"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:31187a9947f5771c9e2a4c5d5c33d8c42f1c0f83b1223277c8faf47da0fcd1dc"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e1713d1f9f294c0cf05ded6f7eff227dde2b19f0d19423fbbeb05fbf5d7c484"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:961c463de6f0de93fc11f1c1f81efc1ec5b5895481cfdf79b3f832e0e242e7e1"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18900f1a13b3b120252fc3583ca1e0fc4d3a33ea98fcf63d33d168a469561056"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4cbbea1a943e742ea649c82f85109b9a9928e61b038923de2813977966acd76"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2714ab61f063a65419278b97f8785ce2440fdb1ef46d9a6703cef9cd38517521"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:823756569f6bea58ff9286cf494abaca5db8652e33ee4a6e7ecb40efbf945088"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11aff145aacfae92b941b95ec5943fb62ea241ec2225b8ecefc4cadadf699893"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-win32.whl", hash = "sha256:4f5f9e3dcece211dc711088a5b264e66e8198b878bdf99619a3a7c54976c118d"},
-    {file = "clickhouse_connect-0.6.6-cp310-cp310-win_amd64.whl", hash = "sha256:8268927ef8d476ef4c81d9562d049f38bc534c4d1d441e072cf8428f08ff6eaa"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5f9cb2ebe0deaa78c942888aad32fa42beb4e75c2377e8784baf3d737c23e5f1"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d502b7f35008facf2774f411eed6b35010923acaac254a8c5683fdf8a11abd62"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87e0f2afe464be0947947d98482eb12b25be8857ae1a31c1aaa17a67f616174d"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f2c517943eeb7663a9d42bd9b737b8ec5513ddcf58f2372f8b2074a315bae2"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa6c2b488cf9558c2b71a2599d812fe4368d5199edaa011731a8bc7bfe019751"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:df9e80d0b3f5614d38026e7e2e7e7412dec942df8d765c082177879b37e678e2"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a20351fb2ae47aac1ae9b1de0585949616baedd6dbdee5272f466a2aea6ec4dd"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af40eaa20998d96198563748a6fd9796843b6f22e9e95b2136aabd917db33fff"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-win32.whl", hash = "sha256:9591a9bfa58ace467544227f83226b22a1554e2db4cfcf658f25f43c9d94e960"},
-    {file = "clickhouse_connect-0.6.6-cp311-cp311-win_amd64.whl", hash = "sha256:3b6f6159f8eddb0cad4d7e0cbad5944e97e0146ee9f416fc663f7bd3d4e9ea46"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8b941c85fe9ddd5e5edf6fc7458563d9e51ad900d95fe0b87b0458be166693a1"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c642696a758fa726c86ca624dd40acded100d79a9f4bd9f5b56ba0ea4dc44099"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57b6b36b316451c1bdc4450f9418c017af84af57d52d03cd4deb85480819a934"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17cfb1d103b47350c3ba824641fb5ba730e6e29274077a6f8975a3394a1abadb"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d52c7e7560666b93c078bf082e4ed87689fd283e6295a6d8d1dd491d4d7b6072"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:0a6d498b689aa09e9d1b0051480a04ecc3509002f54bfb82998d030b4675bb24"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:28c876f7a4713662af2ded7350a0262756ec4da9262bb76cc85cfe2e88015b74"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-win32.whl", hash = "sha256:74bf0a95c7c5644948be0ba9c0abcad7615b806fd2545501862526dbe684db71"},
-    {file = "clickhouse_connect-0.6.6-cp37-cp37m-win_amd64.whl", hash = "sha256:0aaa4194d11cb7513de69b791911ff60b3ad8b86f125446a37347208e9b9ae6d"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b873d138dfedbe761f2d66ad1257ea253394c4f8dcffd6ff34dfb990f13a18b"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7140705d05a05ac39eecf86727ab55985e5dba9d1734df8921cc417853a18b7f"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69085fa0f4e5da5cef4ae5249e19f10d91e57ae78628e49e8853b71b6003dbae"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e6ec081d87cc37be3ecf60b88002c58add76a72b4124525cb5cd28539e7d488"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1afe04eb239b72bc9fa4f1999cd292f82af507cbe1f07546f26a3332c50a294b"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:244bbf7ad92f1f030378412358c47cd377aa6d469b548dba2406a7894c8da2ab"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:69e91bdb25166b6fa4eb55601d86fa57dee82070bce9b97a858c8973615ab8b8"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d2627c8a9625e1c9058cfb5b231a0d0180ed9215d901b601d367de598f27a90d"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-win32.whl", hash = "sha256:87fb937b34b561703eaba5781404736120bab691f4525096d5dfb4b99d4890a6"},
-    {file = "clickhouse_connect-0.6.6-cp38-cp38-win_amd64.whl", hash = "sha256:366c5765e6b7863b3a8d565d5a3b27f9f8731f6f4b016048fa172c6ad6485594"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c1b0d8bee6399f5b68bb0832fae51fd0f5e4bcb539bae2df36d8433b6e38a0b"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3f7e3ead1429ec82b9cd0cf7b807bacf69d895042f75276f63d732378344376"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36df02ebfbfa4dbe3667bf5b3402ff0193d0f682b9aa09d71469c15745473d8e"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa636b0cbbff52c9fafe287d1d818fc9947feaa840c951b8bfd8f8d4d1ee45a0"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af4968b6b48baae43d62c241bee9e1c8f680ee3d054254e3959c2d2fb7d370ee"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a4156de52fe1f9b19f8c3a820d57c012a55644c56a87c8d31ecff89115959d60"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fccbe34878e6202ff5715284cbe57e748d36f4c8ad6217f9c80f84a086013fb9"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70bfe48c0e4340ccf234b691fbd52f32db74649cb84ca28b98a211cc3e30b30c"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-win32.whl", hash = "sha256:9f80b64e2268293a918721e1c122c54e2a1592bb74824fdd70e9add9fbcea31a"},
-    {file = "clickhouse_connect-0.6.6-cp39-cp39-win_amd64.whl", hash = "sha256:04a5030b76ee930b18eb3aeb7847146c2fa29da0feb0ec7dd3a0564a3de944f1"},
-    {file = "clickhouse_connect-0.6.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:75e84c827c8180d5dc66b0e99dba422a3ffd2c7d8ee5ba80e00b9c942dff8a36"},
-    {file = "clickhouse_connect-0.6.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e627061336142d02e9c900a96bcd87372e88f05755bf19b158e68472b99a921"},
-    {file = "clickhouse_connect-0.6.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:194f72e8f3f24c207aa87113b8d11674dab12b35232fd8b7b19b97257796be45"},
-    {file = "clickhouse_connect-0.6.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf755b46089ee6a7f1ab3e24fc6fbacefc54cfefceb0ed81ebf198abf6937dac"},
-    {file = "clickhouse_connect-0.6.6-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:39e58756a13872a24304b1987fafb7d5112ea88469eb55303b1183ebdd7a0be5"},
-    {file = "clickhouse_connect-0.6.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1e29de1264ffa26eb822e57c5715974c9818ae8e16bb114e54352d66947cdf7f"},
-    {file = "clickhouse_connect-0.6.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a74ed74427aaf10d2e8f7697b8ec53479f6068287ea695a5f3d3927db40be3c3"},
-    {file = "clickhouse_connect-0.6.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc910b0f6c93d0d703809fd92cf19b71dcaf8c6d5f328deddae1709061a0aa2"},
-    {file = "clickhouse_connect-0.6.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23b17236e08da8b5d737ccd983db56a2d2222955a49c4b312b12e4a2b4a06c9b"},
-    {file = "clickhouse_connect-0.6.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d4d76560d0ce84d0ba550918433dd1f8da6983edabe2685cd84679cd7a90c179"},
-    {file = "clickhouse_connect-0.6.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:815bd0d5f40174716ffdf1adab066cd0e36c82c81b227224fb7281bdf8734eb6"},
-    {file = "clickhouse_connect-0.6.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82abd319ba51e0c5c2d123e2cf30b1604b0d46f4de694096aa911ddd63701f60"},
-    {file = "clickhouse_connect-0.6.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa3eea5dac3a7cd52523b556ecd05940c4710c96b6e39ec5a05ed7859bddc7f6"},
-    {file = "clickhouse_connect-0.6.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bbc28cdf903b4b2805199ce7d4580814a8b9bb4766ddd835cab46a81e6fcd63"},
-    {file = "clickhouse_connect-0.6.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5fc4deda5a97e672135b4330d81109b443266aa948b09a24a02db58c0fc96bc1"},
-]
-
-[package.dependencies]
-certifi = "*"
-importlib-metadata = "*"
-lz4 = "*"
-pytz = "*"
-urllib3 = ">=1.26"
-zstandard = "*"
-
-[package.extras]
-arrow = ["pyarrow"]
-numpy = ["numpy"]
-orjson = ["orjson"]
-pandas = ["pandas"]
-sqlalchemy = ["sqlalchemy (>1.3.21,<2.0)"]
-
-[[package]]
-name = "colorama"
-version = "0.4.6"
-description = "Cross-platform colored terminal text."
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
-files = [
-    {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
-    {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-
-[[package]]
-name = "colorclass"
-version = "2.2.2"
-description = "Colorful worry-free console applications for Linux, Mac OS X, and Windows."
-optional = false
-python-versions = ">=2.6"
-files = [
-    {file = "colorclass-2.2.2-py2.py3-none-any.whl", hash = "sha256:6f10c273a0ef7a1150b1120b6095cbdd68e5cf36dfd5d0fc957a2500bbf99a55"},
-    {file = "colorclass-2.2.2.tar.gz", hash = "sha256:6d4fe287766166a98ca7bc6f6312daf04a0481b1eda43e7173484051c0ab4366"},
-]
-
-[[package]]
-name = "coloredlogs"
-version = "15.0.1"
-description = "Colored terminal output for Python's logging module"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-files = [
-    {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"},
-    {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"},
-]
-
-[package.dependencies]
-humanfriendly = ">=9.1"
-
-[package.extras]
-cron = ["capturer (>=2.4)"]
-
-[[package]]
-name = "compressed-rtf"
-version = "1.0.6"
-description = "Compressed Rich Text Format (RTF) compression and decompression package"
-optional = false
-python-versions = "*"
-files = [
-    {file = "compressed_rtf-1.0.6.tar.gz", hash = "sha256:c1c827f1d124d24608981a56e8b8691eb1f2a69a78ccad6440e7d92fde1781dd"},
-]
-
-[[package]]
-name = "cryptography"
-version = "41.0.1"
-description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"},
-    {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"},
-    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"},
-    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"},
-    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"},
-    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"},
-    {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"},
-    {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"},
-    {file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"},
-    {file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"},
-    {file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"},
-    {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"},
-    {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"},
-    {file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"},
-    {file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"},
-    {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"},
-    {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"},
-    {file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"},
-    {file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"},
-]
-
-[package.dependencies]
-cffi = ">=1.12"
-
-[package.extras]
-docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
-docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
-nox = ["nox"]
-pep8test = ["black", "check-sdist", "mypy", "ruff"]
-sdist = ["build"]
-ssh = ["bcrypt (>=3.1.5)"]
-test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
-test-randomorder = ["pytest-randomly"]
-
-[[package]]
-name = "dataclasses-json"
-version = "0.5.9"
-description = "Easily serialize dataclasses to and from JSON"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "dataclasses-json-0.5.9.tar.gz", hash = "sha256:e9ac87b73edc0141aafbce02b44e93553c3123ad574958f0fe52a534b6707e8e"},
-    {file = "dataclasses_json-0.5.9-py3-none-any.whl", hash = "sha256:1280542631df1c375b7bc92e5b86d39e06c44760d7e3571a537b3b8acabf2f0c"},
-]
-
-[package.dependencies]
-marshmallow = ">=3.3.0,<4.0.0"
-marshmallow-enum = ">=1.5.1,<2.0.0"
-typing-inspect = ">=0.4.0"
-
-[package.extras]
-dev = ["flake8", "hypothesis", "ipython", "mypy (>=0.710)", "portray", "pytest (>=7.2.0)", "setuptools", "simplejson", "twine", "types-dataclasses", "wheel"]
-
-[[package]]
-name = "duckdb"
-version = "0.8.1"
-description = "DuckDB embedded database"
-optional = false
-python-versions = "*"
-files = [
-    {file = "duckdb-0.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:14781d21580ee72aba1f5dcae7734674c9b6c078dd60470a08b2b420d15b996d"},
-    {file = "duckdb-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f13bf7ab0e56ddd2014ef762ae4ee5ea4df5a69545ce1191b8d7df8118ba3167"},
-    {file = "duckdb-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4032042d8363e55365bbca3faafc6dc336ed2aad088f10ae1a534ebc5bcc181"},
-    {file = "duckdb-0.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a71bd8f0b0ca77c27fa89b99349ef22599ffefe1e7684ae2e1aa2904a08684"},
-    {file = "duckdb-0.8.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24568d6e48f3dbbf4a933109e323507a46b9399ed24c5d4388c4987ddc694fd0"},
-    {file = "duckdb-0.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297226c0dadaa07f7c5ae7cbdb9adba9567db7b16693dbd1b406b739ce0d7924"},
-    {file = "duckdb-0.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5792cf777ece2c0591194006b4d3e531f720186102492872cb32ddb9363919cf"},
-    {file = "duckdb-0.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:12803f9f41582b68921d6b21f95ba7a51e1d8f36832b7d8006186f58c3d1b344"},
-    {file = "duckdb-0.8.1-cp310-cp310-win32.whl", hash = "sha256:d0953d5a2355ddc49095e7aef1392b7f59c5be5cec8cdc98b9d9dc1f01e7ce2b"},
-    {file = "duckdb-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:6e6583c98a7d6637e83bcadfbd86e1f183917ea539f23b6b41178f32f813a5eb"},
-    {file = "duckdb-0.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fad7ed0d4415f633d955ac24717fa13a500012b600751d4edb050b75fb940c25"},
-    {file = "duckdb-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81ae602f34d38d9c48dd60f94b89f28df3ef346830978441b83c5b4eae131d08"},
-    {file = "duckdb-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d75cfe563aaa058d3b4ccaaa371c6271e00e3070df5de72361fd161b2fe6780"},
-    {file = "duckdb-0.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbb55e7a3336f2462e5e916fc128c47fe1c03b6208d6bd413ac11ed95132aa0"},
-    {file = "duckdb-0.8.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6df53efd63b6fdf04657385a791a4e3c4fb94bfd5db181c4843e2c46b04fef5"},
-    {file = "duckdb-0.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b188b80b70d1159b17c9baaf541c1799c1ce8b2af4add179a9eed8e2616be96"},
-    {file = "duckdb-0.8.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ad481ee353f31250b45d64b4a104e53b21415577943aa8f84d0af266dc9af85"},
-    {file = "duckdb-0.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1d1b1729993611b1892509d21c21628917625cdbe824a61ce891baadf684b32"},
-    {file = "duckdb-0.8.1-cp311-cp311-win32.whl", hash = "sha256:2d8f9cc301e8455a4f89aa1088b8a2d628f0c1f158d4cf9bc78971ed88d82eea"},
-    {file = "duckdb-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:07457a43605223f62d93d2a5a66b3f97731f79bbbe81fdd5b79954306122f612"},
-    {file = "duckdb-0.8.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2c8062c3e978dbcd80d712ca3e307de8a06bd4f343aa457d7dd7294692a3842"},
-    {file = "duckdb-0.8.1-cp36-cp36m-win32.whl", hash = "sha256:fad486c65ae944eae2de0d590a0a4fb91a9893df98411d66cab03359f9cba39b"},
-    {file = "duckdb-0.8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:86fa4506622c52d2df93089c8e7075f1c4d0ba56f4bf27faebde8725355edf32"},
-    {file = "duckdb-0.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:60e07a62782f88420046e30cc0e3de842d0901c4fd5b8e4d28b73826ec0c3f5e"},
-    {file = "duckdb-0.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f18563675977f8cbf03748efee0165b4c8ef64e0cbe48366f78e2914d82138bb"},
-    {file = "duckdb-0.8.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16e179443832bea8439ae4dff93cf1e42c545144ead7a4ef5f473e373eea925a"},
-    {file = "duckdb-0.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a413d5267cb41a1afe69d30dd6d4842c588256a6fed7554c7e07dad251ede095"},
-    {file = "duckdb-0.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3784680df59eadd683b0a4c2375d451a64470ca54bd171c01e36951962b1d332"},
-    {file = "duckdb-0.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:67a1725c2b01f9b53571ecf3f92959b652f60156c1c48fb35798302e39b3c1a2"},
-    {file = "duckdb-0.8.1-cp37-cp37m-win32.whl", hash = "sha256:197d37e2588c5ad063e79819054eedb7550d43bf1a557d03ba8f8f67f71acc42"},
-    {file = "duckdb-0.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:3843feb79edf100800f5037c32d5d5a5474fb94b32ace66c707b96605e7c16b2"},
-    {file = "duckdb-0.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:624c889b0f2d656794757b3cc4fc58030d5e285f5ad2ef9fba1ea34a01dab7fb"},
-    {file = "duckdb-0.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fcbe3742d77eb5add2d617d487266d825e663270ef90253366137a47eaab9448"},
-    {file = "duckdb-0.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47516c9299d09e9dbba097b9fb339b389313c4941da5c54109df01df0f05e78c"},
-    {file = "duckdb-0.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf1ba718b7522d34399446ebd5d4b9fcac0b56b6ac07bfebf618fd190ec37c1d"},
-    {file = "duckdb-0.8.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e36e35d38a9ae798fe8cf6a839e81494d5b634af89f4ec9483f4d0a313fc6bdb"},
-    {file = "duckdb-0.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23493313f88ce6e708a512daacad13e83e6d1ea0be204b175df1348f7fc78671"},
-    {file = "duckdb-0.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1fb9bf0b6f63616c8a4b9a6a32789045e98c108df100e6bac783dc1e36073737"},
-    {file = "duckdb-0.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:12fc13ecd5eddd28b203b9e3999040d3a7374a8f4b833b04bd26b8c5685c2635"},
-    {file = "duckdb-0.8.1-cp38-cp38-win32.whl", hash = "sha256:a12bf4b18306c9cb2c9ba50520317e6cf2de861f121d6f0678505fa83468c627"},
-    {file = "duckdb-0.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e4e809358b9559c00caac4233e0e2014f3f55cd753a31c4bcbbd1b55ad0d35e4"},
-    {file = "duckdb-0.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7acedfc00d97fbdb8c3d120418c41ef3cb86ef59367f3a9a30dff24470d38680"},
-    {file = "duckdb-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:99bfe264059cdc1e318769103f656f98e819cd4e231cd76c1d1a0327f3e5cef8"},
-    {file = "duckdb-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:538b225f361066231bc6cd66c04a5561de3eea56115a5dd773e99e5d47eb1b89"},
-    {file = "duckdb-0.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae0be3f71a18cd8492d05d0fc1bc67d01d5a9457b04822d025b0fc8ee6efe32e"},
-    {file = "duckdb-0.8.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd82ba63b58672e46c8ec60bc9946aa4dd7b77f21c1ba09633d8847ad9eb0d7b"},
-    {file = "duckdb-0.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:780a34559aaec8354e83aa4b7b31b3555f1b2cf75728bf5ce11b89a950f5cdd9"},
-    {file = "duckdb-0.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:01f0d4e9f7103523672bda8d3f77f440b3e0155dd3b2f24997bc0c77f8deb460"},
-    {file = "duckdb-0.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31f692decb98c2d57891da27180201d9e93bb470a3051fcf413e8da65bca37a5"},
-    {file = "duckdb-0.8.1-cp39-cp39-win32.whl", hash = "sha256:e7fe93449cd309bbc67d1bf6f6392a6118e94a9a4479ab8a80518742e855370a"},
-    {file = "duckdb-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:81d670bc6807672f038332d9bf587037aabdd741b0810de191984325ed307abd"},
-    {file = "duckdb-0.8.1.tar.gz", hash = "sha256:a54d37f4abc2afc4f92314aaa56ecf215a411f40af4bffe1e86bd25e62aceee9"},
-]
-
-[[package]]
-name = "easygui"
-version = "0.98.3"
-description = "EasyGUI is a module for very simple, very easy GUI programming in Python.  EasyGUI is different from other GUI generators in that EasyGUI is NOT event-driven.  Instead, all GUI interactions are invoked by simple function calls."
-optional = false
-python-versions = "*"
-files = [
-    {file = "easygui-0.98.3-py2.py3-none-any.whl", hash = "sha256:33498710c68b5376b459cd3fc48d1d1f33822139eb3ed01defbc0528326da3ba"},
-    {file = "easygui-0.98.3.tar.gz", hash = "sha256:d653ff79ee1f42f63b5a090f2f98ce02335d86ad8963b3ce2661805cafe99a04"},
-]
-
-[[package]]
-name = "ebcdic"
-version = "1.1.1"
-description = "Additional EBCDIC codecs"
-optional = false
-python-versions = "*"
-files = [
-    {file = "ebcdic-1.1.1-py2.py3-none-any.whl", hash = "sha256:33b4cb729bc2d0bf46cc1847b0e5946897cb8d3f53520c5b9aa5fa98d7e735f1"},
-]
-
-[[package]]
-name = "et-xmlfile"
-version = "1.1.0"
-description = "An implementation of lxml.xmlfile for the standard library"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
-    {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
-]
-
-[[package]]
-name = "exceptiongroup"
-version = "1.1.2"
-description = "Backport of PEP 654 (exception groups)"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
-    {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
-]
-
-[package.extras]
-test = ["pytest (>=6)"]
-
-[[package]]
-name = "extract-msg"
-version = "0.41.5"
-description = "Extracts emails and attachments saved in Microsoft Outlook's .msg files"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "extract_msg-0.41.5-py2.py3-none-any.whl", hash = "sha256:ad70dcdab3701b0fae554168c9642ad4ebef7f2ec283313c55e895a6518911e5"},
-    {file = "extract_msg-0.41.5.tar.gz", hash = "sha256:99d4fdc0c0912c836370bf9fbb6e77558bb978499c1b5fdd31634684e323885c"},
-]
-
-[package.dependencies]
-beautifulsoup4 = ">=4.11.1,<4.13"
-chardet = ">=4.0.0,<6"
-compressed-rtf = ">=1.0.6,<2"
-ebcdic = ">=1.1.1,<2"
-imapclient = ">=2.3.0,<3"
-olefile = "0.46"
-red-black-tree-mod = "1.20"
-RTFDE = "0.0.2"
-tzlocal = ">=4.2,<6"
-
-[package.extras]
-all = ["extract-msg[mime]"]
-mime = ["python-magic (>=0.4.27,<0.5)"]
-
-[[package]]
-name = "fastapi"
-version = "0.100.0"
-description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "fastapi-0.100.0-py3-none-any.whl", hash = "sha256:271662daf986da8fa98dc2b7c7f61c4abdfdccfb4786d79ed8b2878f172c6d5f"},
-    {file = "fastapi-0.100.0.tar.gz", hash = "sha256:acb5f941ea8215663283c10018323ba7ea737c571b67fc7e88e9469c7eb1d12e"},
-]
-
-[package.dependencies]
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0"
-starlette = ">=0.27.0,<0.28.0"
-typing-extensions = ">=4.5.0"
-
-[package.extras]
-all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
-
-[[package]]
-name = "filelock"
-version = "3.12.2"
-description = "A platform independent file lock."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"},
-    {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"},
-]
-
-[package.extras]
-docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
-
-[[package]]
-name = "filetype"
-version = "1.2.0"
-description = "Infer file type and MIME type of any file/buffer. No external dependencies."
-optional = false
-python-versions = "*"
-files = [
-    {file = "filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25"},
-    {file = "filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb"},
-]
-
-[[package]]
-name = "flatbuffers"
-version = "23.5.26"
-description = "The FlatBuffers serialization format for Python"
-optional = false
-python-versions = "*"
-files = [
-    {file = "flatbuffers-23.5.26-py2.py3-none-any.whl", hash = "sha256:c0ff356da363087b915fde4b8b45bdda73432fc17cddb3c8157472eab1422ad1"},
-    {file = "flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89"},
-]
-
-[[package]]
-name = "frozenlist"
-version = "1.3.3"
-description = "A list-like structure which implements collections.abc.MutableSequence"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"},
-    {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"},
-    {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"},
-    {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"},
-    {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"},
-    {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"},
-    {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"},
-    {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"},
-    {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"},
-    {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"},
-    {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"},
-    {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"},
-    {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"},
-    {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"},
-    {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"},
-    {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"},
-    {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"},
-    {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"},
-    {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"},
-    {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"},
-    {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"},
-    {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"},
-    {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"},
-    {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"},
-    {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"},
-    {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"},
-    {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"},
-    {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"},
-    {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"},
-    {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"},
-    {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"},
-    {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"},
-    {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"},
-    {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"},
-    {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"},
-    {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"},
-    {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"},
-    {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"},
-    {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"},
-    {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"},
-    {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"},
-    {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"},
-    {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"},
-    {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"},
-    {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"},
-    {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"},
-    {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"},
-    {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"},
-    {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"},
-    {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"},
-    {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"},
-    {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"},
-    {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"},
-    {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"},
-    {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"},
-    {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"},
-    {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"},
-    {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"},
-    {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"},
-    {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"},
-    {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"},
-    {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"},
-]
-
-[[package]]
-name = "fsspec"
-version = "2023.6.0"
-description = "File-system specification"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "fsspec-2023.6.0-py3-none-any.whl", hash = "sha256:1cbad1faef3e391fba6dc005ae9b5bdcbf43005c9167ce78c915549c352c869a"},
-    {file = "fsspec-2023.6.0.tar.gz", hash = "sha256:d0b2f935446169753e7a5c5c55681c54ea91996cc67be93c39a154fb3a2742af"},
-]
-
-[package.extras]
-abfs = ["adlfs"]
-adl = ["adlfs"]
-arrow = ["pyarrow (>=1)"]
-dask = ["dask", "distributed"]
-devel = ["pytest", "pytest-cov"]
-dropbox = ["dropbox", "dropboxdrivefs", "requests"]
-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"]
-fuse = ["fusepy"]
-gcs = ["gcsfs"]
-git = ["pygit2"]
-github = ["requests"]
-gs = ["gcsfs"]
-gui = ["panel"]
-hdfs = ["pyarrow (>=1)"]
-http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"]
-libarchive = ["libarchive-c"]
-oci = ["ocifs"]
-s3 = ["s3fs"]
-sftp = ["paramiko"]
-smb = ["smbprotocol"]
-ssh = ["paramiko"]
-tqdm = ["tqdm"]
-
-[[package]]
-name = "gpt4all"
-version = "1.0.3"
-description = "Python bindings for GPT4All"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "gpt4all-1.0.3-py3-none-macosx_10_9_universal2.whl", hash = "sha256:11bbc8bdb183b100b57e3e8e0c67650cd84e49d9b875dd15c8bb26cfcf72988d"},
-    {file = "gpt4all-1.0.3-py3-none-manylinux1_x86_64.whl", hash = "sha256:75248b2f160bd7834b807196395d51792cd3e41969c870a418566d1007ec5c83"},
-    {file = "gpt4all-1.0.3-py3-none-win_amd64.whl", hash = "sha256:dcb4901f6320d938bc267ee0b28eaee8676221d22ecbf31b00246d0b4973a31a"},
-]
-
-[package.dependencies]
-requests = "*"
-tqdm = "*"
-
-[package.extras]
-dev = ["black", "isort", "mkautodoc", "mkdocs-jupyter", "mkdocs-material", "mkdocstrings[python]", "pytest", "setuptools", "twine", "wheel"]
-
-[[package]]
-name = "greenlet"
-version = "2.0.2"
-description = "Lightweight in-process concurrent programming"
-optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
-files = [
-    {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"},
-    {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"},
-    {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"},
-    {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"},
-    {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"},
-    {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"},
-    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"},
-    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"},
-    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"},
-    {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"},
-    {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"},
-    {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"},
-    {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"},
-    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"},
-    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"},
-    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"},
-    {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"},
-    {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"},
-    {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"},
-    {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"},
-    {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"},
-    {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"},
-    {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"},
-    {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"},
-    {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"},
-    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"},
-    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"},
-    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"},
-    {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"},
-    {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"},
-    {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"},
-    {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"},
-    {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"},
-    {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"},
-    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"},
-    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"},
-    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"},
-    {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"},
-    {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"},
-    {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"},
-    {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"},
-    {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"},
-    {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"},
-    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"},
-    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"},
-    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"},
-    {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"},
-    {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"},
-    {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"},
-    {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"},
-    {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"},
-    {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"},
-    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"},
-    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"},
-    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"},
-    {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"},
-    {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"},
-    {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"},
-    {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"},
-    {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"},
-]
-
-[package.extras]
-docs = ["Sphinx", "docutils (<0.18)"]
-test = ["objgraph", "psutil"]
-
-[[package]]
-name = "h11"
-version = "0.14.0"
-description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
-    {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
-]
-
-[[package]]
-name = "hnswlib"
-version = "0.7.0"
-description = "hnswlib"
-optional = false
-python-versions = "*"
-files = [
-    {file = "hnswlib-0.7.0.tar.gz", hash = "sha256:bc459668e7e44bb7454b256b90c98c5af750653919d9a91698dafcf416cf64c4"},
-]
-
-[package.dependencies]
-numpy = "*"
-
-[[package]]
-name = "httptools"
-version = "0.6.0"
-description = "A collection of framework independent HTTP protocol utils."
-optional = false
-python-versions = ">=3.5.0"
-files = [
-    {file = "httptools-0.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:818325afee467d483bfab1647a72054246d29f9053fd17cc4b86cda09cc60339"},
-    {file = "httptools-0.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72205730bf1be875003692ca54a4a7c35fac77b4746008966061d9d41a61b0f5"},
-    {file = "httptools-0.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33eb1d4e609c835966e969a31b1dedf5ba16b38cab356c2ce4f3e33ffa94cad3"},
-    {file = "httptools-0.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdc6675ec6cb79d27e0575750ac6e2b47032742e24eed011b8db73f2da9ed40"},
-    {file = "httptools-0.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:463c3bc5ef64b9cf091be9ac0e0556199503f6e80456b790a917774a616aff6e"},
-    {file = "httptools-0.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82f228b88b0e8c6099a9c4757ce9fdbb8b45548074f8d0b1f0fc071e35655d1c"},
-    {file = "httptools-0.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:0781fedc610293a2716bc7fa142d4c85e6776bc59d617a807ff91246a95dea35"},
-    {file = "httptools-0.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:721e503245d591527cddd0f6fd771d156c509e831caa7a57929b55ac91ee2b51"},
-    {file = "httptools-0.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:274bf20eeb41b0956e34f6a81f84d26ed57c84dd9253f13dcb7174b27ccd8aaf"},
-    {file = "httptools-0.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:259920bbae18740a40236807915def554132ad70af5067e562f4660b62c59b90"},
-    {file = "httptools-0.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03bfd2ae8a2d532952ac54445a2fb2504c804135ed28b53fefaf03d3a93eb1fd"},
-    {file = "httptools-0.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f959e4770b3fc8ee4dbc3578fd910fab9003e093f20ac8c621452c4d62e517cb"},
-    {file = "httptools-0.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e22896b42b95b3237eccc42278cd72c0df6f23247d886b7ded3163452481e38"},
-    {file = "httptools-0.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:38f3cafedd6aa20ae05f81f2e616ea6f92116c8a0f8dcb79dc798df3356836e2"},
-    {file = "httptools-0.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47043a6e0ea753f006a9d0dd076a8f8c99bc0ecae86a0888448eb3076c43d717"},
-    {file = "httptools-0.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a541579bed0270d1ac10245a3e71e5beeb1903b5fbbc8d8b4d4e728d48ff1d"},
-    {file = "httptools-0.6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65d802e7b2538a9756df5acc062300c160907b02e15ed15ba035b02bce43e89c"},
-    {file = "httptools-0.6.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:26326e0a8fe56829f3af483200d914a7cd16d8d398d14e36888b56de30bec81a"},
-    {file = "httptools-0.6.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e41ccac9e77cd045f3e4ee0fc62cbf3d54d7d4b375431eb855561f26ee7a9ec4"},
-    {file = "httptools-0.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e748fc0d5c4a629988ef50ac1aef99dfb5e8996583a73a717fc2cac4ab89932"},
-    {file = "httptools-0.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cf8169e839a0d740f3d3c9c4fa630ac1a5aaf81641a34575ca6773ed7ce041a1"},
-    {file = "httptools-0.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5dcc14c090ab57b35908d4a4585ec5c0715439df07be2913405991dbb37e049d"},
-    {file = "httptools-0.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0b0571806a5168013b8c3d180d9f9d6997365a4212cb18ea20df18b938aa0b"},
-    {file = "httptools-0.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fb4a608c631f7dcbdf986f40af7a030521a10ba6bc3d36b28c1dc9e9035a3c0"},
-    {file = "httptools-0.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:93f89975465133619aea8b1952bc6fa0e6bad22a447c6d982fc338fbb4c89649"},
-    {file = "httptools-0.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:73e9d66a5a28b2d5d9fbd9e197a31edd02be310186db423b28e6052472dc8201"},
-    {file = "httptools-0.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:22c01fcd53648162730a71c42842f73b50f989daae36534c818b3f5050b54589"},
-    {file = "httptools-0.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f96d2a351b5625a9fd9133c95744e8ca06f7a4f8f0b8231e4bbaae2c485046a"},
-    {file = "httptools-0.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72ec7c70bd9f95ef1083d14a755f321d181f046ca685b6358676737a5fecd26a"},
-    {file = "httptools-0.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b703d15dbe082cc23266bf5d9448e764c7cb3fcfe7cb358d79d3fd8248673ef9"},
-    {file = "httptools-0.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82c723ed5982f8ead00f8e7605c53e55ffe47c47465d878305ebe0082b6a1755"},
-    {file = "httptools-0.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b0a816bb425c116a160fbc6f34cece097fd22ece15059d68932af686520966bd"},
-    {file = "httptools-0.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dea66d94e5a3f68c5e9d86e0894653b87d952e624845e0b0e3ad1c733c6cc75d"},
-    {file = "httptools-0.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:23b09537086a5a611fad5696fc8963d67c7e7f98cb329d38ee114d588b0b74cd"},
-    {file = "httptools-0.6.0.tar.gz", hash = "sha256:9fc6e409ad38cbd68b177cd5158fc4042c796b82ca88d99ec78f07bed6c6b796"},
-]
-
-[package.extras]
-test = ["Cython (>=0.29.24,<0.30.0)"]
-
-[[package]]
-name = "huggingface-hub"
-version = "0.16.4"
-description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
-optional = false
-python-versions = ">=3.7.0"
-files = [
-    {file = "huggingface_hub-0.16.4-py3-none-any.whl", hash = "sha256:0d3df29932f334fead024afc7cb4cc5149d955238b8b5e42dcf9740d6995a349"},
-    {file = "huggingface_hub-0.16.4.tar.gz", hash = "sha256:608c7d4f3d368b326d1747f91523dbd1f692871e8e2e7a4750314a2dd8b63e14"},
-]
-
-[package.dependencies]
-filelock = "*"
-fsspec = "*"
-packaging = ">=20.9"
-pyyaml = ">=5.1"
-requests = "*"
-tqdm = ">=4.42.1"
-typing-extensions = ">=3.7.4.3"
-
-[package.extras]
-all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "black (>=23.1,<24.0)", "gradio", "jedi", "mypy (==0.982)", "numpy", "pydantic", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.0.241)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "urllib3 (<2.0)"]
-cli = ["InquirerPy (==0.3.4)"]
-dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "black (>=23.1,<24.0)", "gradio", "jedi", "mypy (==0.982)", "numpy", "pydantic", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.0.241)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "urllib3 (<2.0)"]
-fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
-inference = ["aiohttp", "pydantic"]
-quality = ["black (>=23.1,<24.0)", "mypy (==0.982)", "ruff (>=0.0.241)"]
-tensorflow = ["graphviz", "pydot", "tensorflow"]
-testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
-torch = ["torch"]
-typing = ["pydantic", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3"]
-
-[[package]]
-name = "humanfriendly"
-version = "10.0"
-description = "Human friendly output for text interfaces using Python"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-files = [
-    {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"},
-    {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"},
-]
-
-[package.dependencies]
-pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""}
-
-[[package]]
-name = "idna"
-version = "3.4"
-description = "Internationalized Domain Names in Applications (IDNA)"
-optional = false
-python-versions = ">=3.5"
-files = [
-    {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
-    {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
-]
-
-[[package]]
-name = "imapclient"
-version = "2.3.1"
-description = "Easy-to-use, Pythonic and complete IMAP client library"
-optional = false
-python-versions = "*"
-files = [
-    {file = "IMAPClient-2.3.1-py2.py3-none-any.whl", hash = "sha256:057f28025d2987c63e065afb0e4370b0b850b539b0e1494cea0427e88130108c"},
-    {file = "IMAPClient-2.3.1.zip", hash = "sha256:26ea995664fae3a88b878ebce2aff7402931697b86658b7882043ddb01b0e6ba"},
-]
-
-[package.dependencies]
-six = "*"
-
-[package.extras]
-doc = ["sphinx"]
-test = ["mock (>=1.3.0)"]
-
-[[package]]
-name = "importlib-metadata"
-version = "6.8.0"
-description = "Read metadata from Python packages"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
-    {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
-]
-
-[package.dependencies]
-zipp = ">=0.5"
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-perf = ["ipython"]
-testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
-
-[[package]]
-name = "jinja2"
-version = "3.1.2"
-description = "A very fast and expressive template engine."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
-    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=2.0"
-
-[package.extras]
-i18n = ["Babel (>=2.7)"]
-
-[[package]]
-name = "joblib"
-version = "1.3.1"
-description = "Lightweight pipelining with Python functions"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "joblib-1.3.1-py3-none-any.whl", hash = "sha256:89cf0529520e01b3de7ac7b74a8102c90d16d54c64b5dd98cafcd14307fdf915"},
-    {file = "joblib-1.3.1.tar.gz", hash = "sha256:1f937906df65329ba98013dc9692fe22a4c5e4a648112de500508b18a21b41e3"},
-]
-
-[[package]]
-name = "langchain"
-version = "0.0.261"
-description = "Building applications with LLMs through composability"
-optional = false
-python-versions = ">=3.8.1,<4.0"
-files = [
-    {file = "langchain-0.0.261-py3-none-any.whl", hash = "sha256:d2aa7c48c62e9febd7440d06eb067066ce2623db6d8b367f2742c9a78c315ce8"},
-    {file = "langchain-0.0.261.tar.gz", hash = "sha256:1ec501b8323811bf8fa2db10b7703a654c57235646344eefdd0bae764c9e4335"},
-]
-
-[package.dependencies]
-aiohttp = ">=3.8.3,<4.0.0"
-async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""}
-dataclasses-json = ">=0.5.7,<0.6.0"
-langsmith = ">=0.0.11,<0.1.0"
-numexpr = ">=2.8.4,<3.0.0"
-numpy = ">=1,<2"
-openapi-schema-pydantic = ">=1.2,<2.0"
-pydantic = ">=1,<2"
-PyYAML = ">=5.3"
-requests = ">=2,<3"
-SQLAlchemy = ">=1.4,<3"
-tenacity = ">=8.1.0,<9.0.0"
-
-[package.extras]
-all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "amadeus (>=8.1.0)", "anthropic (>=0.3,<0.4)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.9,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clarifai (>=9.1.0)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=4,<5)", "deeplake (>=3.6.8,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=3.8.3,<4.0.0)", "elasticsearch (>=8,<9)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jina (>=3.14,<4.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.6,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "libdeeplake (>=0.0.60,<0.0.61)", "librosa (>=0.10.0.post2,<0.11.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "marqo (>=0.11.0,<0.12.0)", "momento (>=1.5.0,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<3.0.0)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "octoai-sdk (>=0.1.1,<0.2.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "python-arango (>=7.5.9,<8.0.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.3.1,<2.0.0)", "rdflib (>=6.3.2,<7.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.7.1,<0.8.0)", "spacy (>=3,<4)", "steamship (>=2.16.9,<3.0.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.4.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)", "xinference (>=0.0.6,<0.0.7)"]
-azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b6)", "openai (>=0,<1)"]
-clarifai = ["clarifai (>=9.1.0)"]
-cohere = ["cohere (>=4,<5)"]
-docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"]
-embeddings = ["sentence-transformers (>=2,<3)"]
-extended-testing = ["amazon-textract-caller (<2)", "anthropic (>=0.3,<0.4)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.0.7,<0.0.8)", "chardet (>=5.1.0,<6.0.0)", "esprima (>=4.0.1,<5.0.0)", "feedparser (>=6.0.10,<7.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "openai (>=0,<1)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tqdm (>=4.48.0)", "xata (>=1.0.0a7,<2.0.0)", "xinference (>=0.0.6,<0.0.7)", "xmltodict (>=0.13.0,<0.14.0)", "zep-python (>=0.32)"]
-javascript = ["esprima (>=4.0.1,<5.0.0)"]
-llms = ["anthropic (>=0.3,<0.4)", "clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (>=0,<1)", "openllm (>=0.1.19)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)", "xinference (>=0.0.6,<0.0.7)"]
-openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.4.0)"]
-qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"]
-scheduled-testing = ["openai (>=0,<1)"]
-text-helpers = ["chardet (>=5.1.0,<6.0.0)"]
-
-[[package]]
-name = "langsmith"
-version = "0.0.21"
-description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
-optional = false
-python-versions = ">=3.8.1,<4.0"
-files = [
-    {file = "langsmith-0.0.21-py3-none-any.whl", hash = "sha256:a04c6eb3b4fc6205b15a559705f726fd0114ee2b3bd8668a0bd11cf29d5c5992"},
-    {file = "langsmith-0.0.21.tar.gz", hash = "sha256:ec90ddab6beee6c344cf0ed8ae7d68948740cf98e119dd97c571f3190555644e"},
-]
-
-[package.dependencies]
-pydantic = ">=1,<2"
-requests = ">=2,<3"
-
-[[package]]
-name = "lark-parser"
-version = "0.12.0"
-description = "a modern parsing library"
-optional = false
-python-versions = "*"
-files = [
-    {file = "lark-parser-0.12.0.tar.gz", hash = "sha256:15967db1f1214013dca65b1180745047b9be457d73da224fcda3d9dd4e96a138"},
-    {file = "lark_parser-0.12.0-py2.py3-none-any.whl", hash = "sha256:0eaf30cb5ba787fe404d73a7d6e61df97b21d5a63ac26c5008c78a494373c675"},
-]
-
-[package.extras]
-atomic-cache = ["atomicwrites"]
-nearley = ["js2py"]
-regex = ["regex"]
-
-[[package]]
-name = "lxml"
-version = "4.9.3"
-description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
-files = [
-    {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"},
-    {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"},
-    {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"},
-    {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"},
-    {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"},
-    {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"},
-    {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"},
-    {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"},
-    {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"},
-    {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"},
-    {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"},
-    {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"},
-    {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"},
-    {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"},
-    {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"},
-    {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"},
-    {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"},
-    {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"},
-    {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"},
-    {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"},
-    {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"},
-    {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"},
-    {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"},
-    {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"},
-    {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"},
-    {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"},
-    {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"},
-    {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"},
-    {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"},
-    {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"},
-    {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"},
-    {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"},
-    {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"},
-    {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"},
-    {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"},
-    {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"},
-    {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"},
-    {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"},
-    {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"},
-    {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"},
-    {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"},
-    {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"},
-    {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"},
-    {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"},
-    {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"},
-    {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"},
-    {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"},
-    {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"},
-    {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"},
-    {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"},
-    {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"},
-    {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"},
-    {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"},
-    {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"},
-    {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"},
-    {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"},
-    {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"},
-    {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"},
-    {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"},
-    {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"},
-    {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"},
-    {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"},
-    {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"},
-    {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"},
-    {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"},
-    {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"},
-    {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"},
-    {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"},
-    {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"},
-    {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"},
-    {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"},
-    {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"},
-]
-
-[package.extras]
-cssselect = ["cssselect (>=0.7)"]
-html5 = ["html5lib"]
-htmlsoup = ["BeautifulSoup4"]
-source = ["Cython (>=0.29.35)"]
-
-[[package]]
-name = "lz4"
-version = "4.3.2"
-description = "LZ4 Bindings for Python"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "lz4-4.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1c4c100d99eed7c08d4e8852dd11e7d1ec47a3340f49e3a96f8dfbba17ffb300"},
-    {file = "lz4-4.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:edd8987d8415b5dad25e797043936d91535017237f72fa456601be1479386c92"},
-    {file = "lz4-4.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7c50542b4ddceb74ab4f8b3435327a0861f06257ca501d59067a6a482535a77"},
-    {file = "lz4-4.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f5614d8229b33d4a97cb527db2a1ac81308c6e796e7bdb5d1309127289f69d5"},
-    {file = "lz4-4.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f00a9ba98f6364cadda366ae6469b7b3568c0cced27e16a47ddf6b774169270"},
-    {file = "lz4-4.3.2-cp310-cp310-win32.whl", hash = "sha256:b10b77dc2e6b1daa2f11e241141ab8285c42b4ed13a8642495620416279cc5b2"},
-    {file = "lz4-4.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:86480f14a188c37cb1416cdabacfb4e42f7a5eab20a737dac9c4b1c227f3b822"},
-    {file = "lz4-4.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7c2df117def1589fba1327dceee51c5c2176a2b5a7040b45e84185ce0c08b6a3"},
-    {file = "lz4-4.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1f25eb322eeb24068bb7647cae2b0732b71e5c639e4e4026db57618dcd8279f0"},
-    {file = "lz4-4.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8df16c9a2377bdc01e01e6de5a6e4bbc66ddf007a6b045688e285d7d9d61d1c9"},
-    {file = "lz4-4.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f571eab7fec554d3b1db0d666bdc2ad85c81f4b8cb08906c4c59a8cad75e6e22"},
-    {file = "lz4-4.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7211dc8f636ca625abc3d4fb9ab74e5444b92df4f8d58ec83c8868a2b0ff643d"},
-    {file = "lz4-4.3.2-cp311-cp311-win32.whl", hash = "sha256:867664d9ca9bdfce840ac96d46cd8838c9ae891e859eb98ce82fcdf0e103a947"},
-    {file = "lz4-4.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:a6a46889325fd60b8a6b62ffc61588ec500a1883db32cddee9903edfba0b7584"},
-    {file = "lz4-4.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a85b430138882f82f354135b98c320dafb96fc8fe4656573d95ab05de9eb092"},
-    {file = "lz4-4.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65d5c93f8badacfa0456b660285e394e65023ef8071142e0dcbd4762166e1be0"},
-    {file = "lz4-4.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b50f096a6a25f3b2edca05aa626ce39979d63c3b160687c8c6d50ac3943d0ba"},
-    {file = "lz4-4.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:200d05777d61ba1ff8d29cb51c534a162ea0b4fe6d3c28be3571a0a48ff36080"},
-    {file = "lz4-4.3.2-cp37-cp37m-win32.whl", hash = "sha256:edc2fb3463d5d9338ccf13eb512aab61937be50aa70734bcf873f2f493801d3b"},
-    {file = "lz4-4.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:83acfacab3a1a7ab9694333bcb7950fbeb0be21660d236fd09c8337a50817897"},
-    {file = "lz4-4.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a9eec24ec7d8c99aab54de91b4a5a149559ed5b3097cf30249b665689b3d402"},
-    {file = "lz4-4.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:31d72731c4ac6ebdce57cd9a5cabe0aecba229c4f31ba3e2c64ae52eee3fdb1c"},
-    {file = "lz4-4.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83903fe6db92db0be101acedc677aa41a490b561567fe1b3fe68695b2110326c"},
-    {file = "lz4-4.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926b26db87ec8822cf1870efc3d04d06062730ec3279bbbd33ba47a6c0a5c673"},
-    {file = "lz4-4.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e05afefc4529e97c08e65ef92432e5f5225c0bb21ad89dee1e06a882f91d7f5e"},
-    {file = "lz4-4.3.2-cp38-cp38-win32.whl", hash = "sha256:ad38dc6a7eea6f6b8b642aaa0683253288b0460b70cab3216838747163fb774d"},
-    {file = "lz4-4.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:7e2dc1bd88b60fa09b9b37f08553f45dc2b770c52a5996ea52b2b40f25445676"},
-    {file = "lz4-4.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:edda4fb109439b7f3f58ed6bede59694bc631c4b69c041112b1b7dc727fffb23"},
-    {file = "lz4-4.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ca83a623c449295bafad745dcd399cea4c55b16b13ed8cfea30963b004016c9"},
-    {file = "lz4-4.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5ea0e788dc7e2311989b78cae7accf75a580827b4d96bbaf06c7e5a03989bd5"},
-    {file = "lz4-4.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a98b61e504fb69f99117b188e60b71e3c94469295571492a6468c1acd63c37ba"},
-    {file = "lz4-4.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4931ab28a0d1c133104613e74eec1b8bb1f52403faabe4f47f93008785c0b929"},
-    {file = "lz4-4.3.2-cp39-cp39-win32.whl", hash = "sha256:ec6755cacf83f0c5588d28abb40a1ac1643f2ff2115481089264c7630236618a"},
-    {file = "lz4-4.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:4caedeb19e3ede6c7a178968b800f910db6503cb4cb1e9cc9221157572139b49"},
-    {file = "lz4-4.3.2.tar.gz", hash = "sha256:e1431d84a9cfb23e6773e72078ce8e65cad6745816d4cbf9ae67da5ea419acda"},
-]
-
-[package.extras]
-docs = ["sphinx (>=1.6.0)", "sphinx-bootstrap-theme"]
-flake8 = ["flake8"]
-tests = ["psutil", "pytest (!=3.3.0)", "pytest-cov"]
-
-[[package]]
-name = "markdown"
-version = "3.4.3"
-description = "Python implementation of John Gruber's Markdown."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"},
-    {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"},
-]
-
-[package.extras]
-testing = ["coverage", "pyyaml"]
-
-[[package]]
-name = "markupsafe"
-version = "2.1.3"
-description = "Safely add untrusted strings to HTML/XML markup."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
-    {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
-]
-
-[[package]]
-name = "marshmallow"
-version = "3.19.0"
-description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "marshmallow-3.19.0-py3-none-any.whl", hash = "sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b"},
-    {file = "marshmallow-3.19.0.tar.gz", hash = "sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78"},
-]
-
-[package.dependencies]
-packaging = ">=17.0"
-
-[package.extras]
-dev = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)", "pytest", "pytz", "simplejson", "tox"]
-docs = ["alabaster (==0.7.12)", "autodocsumm (==0.2.9)", "sphinx (==5.3.0)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"]
-lint = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)"]
-tests = ["pytest", "pytz", "simplejson"]
-
-[[package]]
-name = "marshmallow-enum"
-version = "1.5.1"
-description = "Enum field for Marshmallow"
-optional = false
-python-versions = "*"
-files = [
-    {file = "marshmallow-enum-1.5.1.tar.gz", hash = "sha256:38e697e11f45a8e64b4a1e664000897c659b60aa57bfa18d44e226a9920b6e58"},
-    {file = "marshmallow_enum-1.5.1-py2.py3-none-any.whl", hash = "sha256:57161ab3dbfde4f57adeb12090f39592e992b9c86d206d02f6bd03ebec60f072"},
-]
-
-[package.dependencies]
-marshmallow = ">=2.0.0"
-
-[[package]]
-name = "monotonic"
-version = "1.6"
-description = "An implementation of time.monotonic() for Python 2 & < 3.3"
-optional = false
-python-versions = "*"
-files = [
-    {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"},
-    {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"},
-]
-
-[[package]]
-name = "mpmath"
-version = "1.3.0"
-description = "Python library for arbitrary-precision floating-point arithmetic"
-optional = false
-python-versions = "*"
-files = [
-    {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"},
-    {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"},
-]
-
-[package.extras]
-develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"]
-docs = ["sphinx"]
-gmpy = ["gmpy2 (>=2.1.0a4)"]
-tests = ["pytest (>=4.6)"]
-
-[[package]]
-name = "msg-parser"
-version = "1.2.0"
-description = "This module enables reading, parsing and converting Microsoft Outlook MSG E-Mail files."
-optional = false
-python-versions = ">=3.4"
-files = [
-    {file = "msg_parser-1.2.0-py2.py3-none-any.whl", hash = "sha256:d47a2f0b2a359cb189fad83cc991b63ea781ecc70d91410324273fbf93e95375"},
-    {file = "msg_parser-1.2.0.tar.gz", hash = "sha256:0de858d4fcebb6c8f6f028da83a17a20fe01cdce67c490779cf43b3b0162aa66"},
-]
-
-[package.dependencies]
-olefile = ">=0.46"
-
-[package.extras]
-rtf = ["compressed-rtf (>=1.0.5)"]
-
-[[package]]
-name = "msoffcrypto-tool"
-version = "5.0.1"
-description = "Python tool and library for decrypting MS Office files with passwords or other keys"
-optional = false
-python-versions = ">=3.7,<4.0"
-files = [
-    {file = "msoffcrypto_tool-5.0.1-py3-none-any.whl", hash = "sha256:2b489c8a2b13bec07b94c8f5ce9054111dec3223ff8bedfd486cae3c299be54b"},
-    {file = "msoffcrypto_tool-5.0.1.tar.gz", hash = "sha256:9efd0ef5cc3e086e2d175e7a5d7b2b8cb59836c896b8a486d362bbca166db645"},
-]
-
-[package.dependencies]
-cryptography = ">=35.0"
-olefile = ">=0.46"
-
-[[package]]
-name = "multidict"
-version = "6.0.4"
-description = "multidict implementation"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"},
-    {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"},
-    {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"},
-    {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"},
-    {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"},
-    {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"},
-    {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"},
-    {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"},
-    {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"},
-    {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"},
-    {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"},
-    {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"},
-    {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"},
-    {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"},
-    {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"},
-    {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"},
-    {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"},
-    {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"},
-    {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"},
-    {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"},
-    {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"},
-    {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"},
-    {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"},
-    {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"},
-    {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"},
-    {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"},
-    {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"},
-    {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"},
-    {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"},
-    {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"},
-    {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"},
-    {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"},
-    {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"},
-    {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"},
-    {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"},
-    {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"},
-    {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"},
-    {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"},
-    {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"},
-    {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"},
-    {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"},
-    {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"},
-    {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"},
-    {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"},
-    {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"},
-    {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"},
-    {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"},
-    {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"},
-    {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"},
-    {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"},
-    {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"},
-    {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"},
-    {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"},
-    {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"},
-    {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"},
-    {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"},
-    {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"},
-    {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"},
-    {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"},
-    {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"},
-    {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"},
-    {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"},
-    {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"},
-    {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"},
-    {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"},
-    {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"},
-    {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"},
-    {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"},
-    {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"},
-    {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"},
-    {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"},
-    {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"},
-    {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"},
-    {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
-]
-
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-optional = false
-python-versions = ">=3.5"
-files = [
-    {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
-    {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
-[[package]]
-name = "networkx"
-version = "3.1"
-description = "Python package for creating and manipulating graphs and networks"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"},
-    {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"},
-]
-
-[package.extras]
-default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"]
-developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"]
-doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"]
-extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"]
-test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"]
-
-[[package]]
-name = "nltk"
-version = "3.8.1"
-description = "Natural Language Toolkit"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "nltk-3.8.1-py3-none-any.whl", hash = "sha256:fd5c9109f976fa86bcadba8f91e47f5e9293bd034474752e92a520f81c93dda5"},
-    {file = "nltk-3.8.1.zip", hash = "sha256:1834da3d0682cba4f2cede2f9aad6b0fafb6461ba451db0efb6f9c39798d64d3"},
-]
-
-[package.dependencies]
-click = "*"
-joblib = "*"
-regex = ">=2021.8.3"
-tqdm = "*"
-
-[package.extras]
-all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"]
-corenlp = ["requests"]
-machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"]
-plot = ["matplotlib"]
-tgrep = ["pyparsing"]
-twitter = ["twython"]
-
-[[package]]
-name = "numexpr"
-version = "2.8.4"
-description = "Fast numerical expression evaluator for NumPy"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "numexpr-2.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a75967d46b6bd56455dd32da6285e5ffabe155d0ee61eef685bbfb8dafb2e484"},
-    {file = "numexpr-2.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db93cf1842f068247de631bfc8af20118bf1f9447cd929b531595a5e0efc9346"},
-    {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bca95f4473b444428061d4cda8e59ac564dc7dc6a1dea3015af9805c6bc2946"},
-    {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e34931089a6bafc77aaae21f37ad6594b98aa1085bb8b45d5b3cd038c3c17d9"},
-    {file = "numexpr-2.8.4-cp310-cp310-win32.whl", hash = "sha256:f3a920bfac2645017110b87ddbe364c9c7a742870a4d2f6120b8786c25dc6db3"},
-    {file = "numexpr-2.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:6931b1e9d4f629f43c14b21d44f3f77997298bea43790cfcdb4dd98804f90783"},
-    {file = "numexpr-2.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9400781553541f414f82eac056f2b4c965373650df9694286b9bd7e8d413f8d8"},
-    {file = "numexpr-2.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ee9db7598dd4001138b482342b96d78110dd77cefc051ec75af3295604dde6a"},
-    {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff5835e8af9a212e8480003d731aad1727aaea909926fd009e8ae6a1cba7f141"},
-    {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:655d84eb09adfee3c09ecf4a89a512225da153fdb7de13c447404b7d0523a9a7"},
-    {file = "numexpr-2.8.4-cp311-cp311-win32.whl", hash = "sha256:5538b30199bfc68886d2be18fcef3abd11d9271767a7a69ff3688defe782800a"},
-    {file = "numexpr-2.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:3f039321d1c17962c33079987b675fb251b273dbec0f51aac0934e932446ccc3"},
-    {file = "numexpr-2.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c867cc36cf815a3ec9122029874e00d8fbcef65035c4a5901e9b120dd5d626a2"},
-    {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:059546e8f6283ccdb47c683101a890844f667fa6d56258d48ae2ecf1b3875957"},
-    {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:845a6aa0ed3e2a53239b89c1ebfa8cf052d3cc6e053c72805e8153300078c0b1"},
-    {file = "numexpr-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:a38664e699526cb1687aefd9069e2b5b9387da7feac4545de446141f1ef86f46"},
-    {file = "numexpr-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eaec59e9bf70ff05615c34a8b8d6c7bd042bd9f55465d7b495ea5436f45319d0"},
-    {file = "numexpr-2.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b318541bf3d8326682ebada087ba0050549a16d8b3fa260dd2585d73a83d20a7"},
-    {file = "numexpr-2.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b076db98ca65eeaf9bd224576e3ac84c05e451c0bd85b13664b7e5f7b62e2c70"},
-    {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f12cc851240f7911a47c91aaf223dba753e98e46dff3017282e633602e76a7"},
-    {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c368aa35ae9b18840e78b05f929d3a7b3abccdba9630a878c7db74ca2368339"},
-    {file = "numexpr-2.8.4-cp38-cp38-win32.whl", hash = "sha256:b96334fc1748e9ec4f93d5fadb1044089d73fb08208fdb8382ed77c893f0be01"},
-    {file = "numexpr-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:a6d2d7740ae83ba5f3531e83afc4b626daa71df1ef903970947903345c37bd03"},
-    {file = "numexpr-2.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:77898fdf3da6bb96aa8a4759a8231d763a75d848b2f2e5c5279dad0b243c8dfe"},
-    {file = "numexpr-2.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df35324666b693f13a016bc7957de7cc4d8801b746b81060b671bf78a52b9037"},
-    {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ac9cfe6d0078c5fc06ba1c1bbd20b8783f28c6f475bbabd3cad53683075cab"},
-    {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3a1f6b24214a1ab826e9c1c99edf1686c8e307547a9aef33910d586f626d01"},
-    {file = "numexpr-2.8.4-cp39-cp39-win32.whl", hash = "sha256:7d71add384adc9119568d7e9ffa8a35b195decae81e0abf54a2b7779852f0637"},
-    {file = "numexpr-2.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:9f096d707290a6a00b6ffdaf581ee37331109fb7b6c8744e9ded7c779a48e517"},
-    {file = "numexpr-2.8.4.tar.gz", hash = "sha256:d5432537418d18691b9115d615d6daa17ee8275baef3edf1afbbf8bc69806147"},
-]
-
-[package.dependencies]
-numpy = ">=1.13.3"
-
-[[package]]
-name = "numpy"
-version = "1.25.1"
-description = "Fundamental package for array computing in Python"
-optional = false
-python-versions = ">=3.9"
-files = [
-    {file = "numpy-1.25.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77d339465dff3eb33c701430bcb9c325b60354698340229e1dff97745e6b3efa"},
-    {file = "numpy-1.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d736b75c3f2cb96843a5c7f8d8ccc414768d34b0a75f466c05f3a739b406f10b"},
-    {file = "numpy-1.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a90725800caeaa160732d6b31f3f843ebd45d6b5f3eec9e8cc287e30f2805bf"},
-    {file = "numpy-1.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c6c9261d21e617c6dc5eacba35cb68ec36bb72adcff0dee63f8fbc899362588"},
-    {file = "numpy-1.25.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0def91f8af6ec4bb94c370e38c575855bf1d0be8a8fbfba42ef9c073faf2cf19"},
-    {file = "numpy-1.25.1-cp310-cp310-win32.whl", hash = "sha256:fd67b306320dcadea700a8f79b9e671e607f8696e98ec255915c0c6d6b818503"},
-    {file = "numpy-1.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:c1516db588987450b85595586605742879e50dcce923e8973f79529651545b57"},
-    {file = "numpy-1.25.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6b82655dd8efeea69dbf85d00fca40013d7f503212bc5259056244961268b66e"},
-    {file = "numpy-1.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e8f6049c4878cb16960fbbfb22105e49d13d752d4d8371b55110941fb3b17800"},
-    {file = "numpy-1.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41a56b70e8139884eccb2f733c2f7378af06c82304959e174f8e7370af112e09"},
-    {file = "numpy-1.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5154b1a25ec796b1aee12ac1b22f414f94752c5f94832f14d8d6c9ac40bcca6"},
-    {file = "numpy-1.25.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38eb6548bb91c421261b4805dc44def9ca1a6eef6444ce35ad1669c0f1a3fc5d"},
-    {file = "numpy-1.25.1-cp311-cp311-win32.whl", hash = "sha256:791f409064d0a69dd20579345d852c59822c6aa087f23b07b1b4e28ff5880fcb"},
-    {file = "numpy-1.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:c40571fe966393b212689aa17e32ed905924120737194b5d5c1b20b9ed0fb171"},
-    {file = "numpy-1.25.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3d7abcdd85aea3e6cdddb59af2350c7ab1ed764397f8eec97a038ad244d2d105"},
-    {file = "numpy-1.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a180429394f81c7933634ae49b37b472d343cccb5bb0c4a575ac8bbc433722f"},
-    {file = "numpy-1.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d412c1697c3853c6fc3cb9751b4915859c7afe6a277c2bf00acf287d56c4e625"},
-    {file = "numpy-1.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e1266411120a4f16fad8efa8e0454d21d00b8c7cee5b5ccad7565d95eb42dd"},
-    {file = "numpy-1.25.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f76aebc3358ade9eacf9bc2bb8ae589863a4f911611694103af05346637df1b7"},
-    {file = "numpy-1.25.1-cp39-cp39-win32.whl", hash = "sha256:247d3ffdd7775bdf191f848be8d49100495114c82c2bd134e8d5d075fb386a1c"},
-    {file = "numpy-1.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:1d5d3c68e443c90b38fdf8ef40e60e2538a27548b39b12b73132456847f4b631"},
-    {file = "numpy-1.25.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:35a9527c977b924042170a0887de727cd84ff179e478481404c5dc66b4170009"},
-    {file = "numpy-1.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d3fe3dd0506a28493d82dc3cf254be8cd0d26f4008a417385cbf1ae95b54004"},
-    {file = "numpy-1.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:012097b5b0d00a11070e8f2e261128c44157a8689f7dedcf35576e525893f4fe"},
-    {file = "numpy-1.25.1.tar.gz", hash = "sha256:9a3a9f3a61480cc086117b426a8bd86869c213fc4072e606f01c4e4b66eb92bf"},
-]
-
-[[package]]
-name = "olefile"
-version = "0.46"
-description = "Python package to parse, read and write Microsoft OLE2 files (Structured Storage or Compound Document, Microsoft Office)"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
-    {file = "olefile-0.46.zip", hash = "sha256:133b031eaf8fd2c9399b78b8bc5b8fcbe4c31e85295749bb17a87cba8f3c3964"},
-]
-
-[[package]]
-name = "oletools"
-version = "0.60.1"
-description = "Python tools to analyze security characteristics of MS Office and OLE files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), for Malware Analysis and Incident Response #DFIR"
-optional = false
-python-versions = "*"
-files = [
-    {file = "oletools-0.60.1-py2.py3-none-any.whl", hash = "sha256:edef92374e688989a39269eb9a11142fb20a023629c23538c849c14d1d1144ea"},
-    {file = "oletools-0.60.1.zip", hash = "sha256:67a796da4c4b8e2feb9a6b2495bef8798a3323a75512de4e5669d9dc9d1fae31"},
-]
-
-[package.dependencies]
-colorclass = "*"
-easygui = "*"
-msoffcrypto-tool = {version = "*", markers = "platform_python_implementation != \"PyPy\" or python_version >= \"3\" and (platform_system != \"Windows\" and platform_system != \"Darwin\")"}
-olefile = ">=0.46"
-pcodedmp = ">=1.2.5"
-pyparsing = ">=2.1.0,<3"
-
-[package.extras]
-full = ["XLMMacroDeobfuscator"]
-
-[[package]]
-name = "onnxruntime"
-version = "1.15.1"
-description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
-optional = false
-python-versions = "*"
-files = [
-    {file = "onnxruntime-1.15.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:baad59e6a763237fa39545325d29c16f98b8a45d2dfc524c67631e2e3ba44d16"},
-    {file = "onnxruntime-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:568c2db848f619a0a93e843c028e9fb4879929d40b04bd60f9ba6eb8d2e93421"},
-    {file = "onnxruntime-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69088d7784bb04dedfd9e883e2c96e4adf8ae0451acdd0abb78d68f59ecc6d9d"},
-    {file = "onnxruntime-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cef43737b2cd886d5d718d100f56ec78c9c476c5db5f8f946e95024978fe754"},
-    {file = "onnxruntime-1.15.1-cp310-cp310-win32.whl", hash = "sha256:79d7e65abb44a47c633ede8e53fe7b9756c272efaf169758c482c983cca98d7e"},
-    {file = "onnxruntime-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:8bc4c47682933a7a2c79808688aad5f12581305e182be552de50783b5438e6bd"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:652b2cb777f76446e3cc41072dd3d1585a6388aeff92b9de656724bc22e241e4"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89b86dbed15740abc385055a29c9673a212600248d702737ce856515bdeddc88"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed5cdd9ee748149a57f4cdfa67187a0d68f75240645a3c688299dcd08742cc98"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f748cce6a70ed38c19658615c55f4eedb9192765a4e9c4bd2682adfe980698d"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-win32.whl", hash = "sha256:e0312046e814c40066e7823da58075992d51364cbe739eeeb2345ec440c3ac59"},
-    {file = "onnxruntime-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:f0980969689cb956c22bd1318b271e1be260060b37f3ddd82c7d63bd7f2d9a79"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:345986cfdbd6f4b20a89b6a6cd9abd3e2ced2926ae0b6e91fefa8149f95c0f09"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d7b3ad75e040f1e95757f69826a11051737b31584938a26d466a0234c6de98"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3603d07b829bcc1c14963a76103e257aade8861eb208173b300cc26e118ec2f8"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3df0625b9295daf1f7409ea55f72e1eeb38d54f5769add53372e79ddc3cf98d"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-win32.whl", hash = "sha256:f68b47fdf1a0406c0292f81ac993e2a2ae3e8b166b436d590eb221f64e8e187a"},
-    {file = "onnxruntime-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:52d762d297cc3f731f54fa65a3e329b813164970671547bef6414d0ed52765c9"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:99228f9f03dc1fc8af89a28c9f942e8bd3e97e894e263abe1a32e4ddb1f6363b"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:45db7f96febb0cf23e3af147f35c4f8de1a37dd252d1cef853c242c2780250cd"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bafc112a36db25c821b90ab747644041cb4218f6575889775a2c12dd958b8c3"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:985693d18f2d46aa34fd44d7f65ff620660b2c8fa4b8ec365c2ca353f0fbdb27"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-win32.whl", hash = "sha256:708eb31b0c04724bf0f01c1309a9e69bbc09b85beb750e5662c8aed29f1ff9fd"},
-    {file = "onnxruntime-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:73d6de4c42dfde1e9dbea04773e6dc23346c8cda9c7e08c6554fafc97ac60138"},
-]
-
-[package.dependencies]
-coloredlogs = "*"
-flatbuffers = "*"
-numpy = ">=1.21.6"
-packaging = "*"
-protobuf = "*"
-sympy = "*"
-
-[[package]]
-name = "openapi-schema-pydantic"
-version = "1.2.4"
-description = "OpenAPI (v3) specification schema as pydantic class"
-optional = false
-python-versions = ">=3.6.1"
-files = [
-    {file = "openapi-schema-pydantic-1.2.4.tar.gz", hash = "sha256:3e22cf58b74a69f752cc7e5f1537f6e44164282db2700cbbcd3bb99ddd065196"},
-    {file = "openapi_schema_pydantic-1.2.4-py3-none-any.whl", hash = "sha256:a932ecc5dcbb308950282088956e94dea069c9823c84e507d64f6b622222098c"},
-]
-
-[package.dependencies]
-pydantic = ">=1.8.2"
-
-[[package]]
-name = "openpyxl"
-version = "3.1.2"
-description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"},
-    {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"},
-]
-
-[package.dependencies]
-et-xmlfile = "*"
-
-[[package]]
-name = "overrides"
-version = "7.3.1"
-description = "A decorator to automatically detect mismatch when overriding a method."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "overrides-7.3.1-py3-none-any.whl", hash = "sha256:6187d8710a935d09b0bcef8238301d6ee2569d2ac1ae0ec39a8c7924e27f58ca"},
-    {file = "overrides-7.3.1.tar.gz", hash = "sha256:8b97c6c1e1681b78cbc9424b138d880f0803c2254c5ebaabdde57bb6c62093f2"},
-]
-
-[[package]]
-name = "packaging"
-version = "23.1"
-description = "Core utilities for Python packages"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
-    {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
-]
-
-[[package]]
-name = "pandas"
-version = "2.0.3"
-description = "Powerful data structures for data analysis, time series, and statistics"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"},
-    {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"},
-    {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"},
-    {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"},
-    {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"},
-    {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"},
-    {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"},
-    {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"},
-    {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"},
-    {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"},
-    {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"},
-    {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"},
-    {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"},
-    {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"},
-    {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"},
-    {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"},
-    {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"},
-    {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"},
-    {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"},
-    {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"},
-    {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"},
-    {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"},
-    {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"},
-    {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"},
-    {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"},
-]
-
-[package.dependencies]
-numpy = [
-    {version = ">=1.21.0", markers = "python_version >= \"3.10\""},
-    {version = ">=1.23.2", markers = "python_version >= \"3.11\""},
-]
-python-dateutil = ">=2.8.2"
-pytz = ">=2020.1"
-tzdata = ">=2022.1"
-
-[package.extras]
-all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"]
-aws = ["s3fs (>=2021.08.0)"]
-clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"]
-compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"]
-computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"]
-excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"]
-feather = ["pyarrow (>=7.0.0)"]
-fss = ["fsspec (>=2021.07.0)"]
-gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"]
-hdf5 = ["tables (>=3.6.1)"]
-html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"]
-mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"]
-output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"]
-parquet = ["pyarrow (>=7.0.0)"]
-performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"]
-plot = ["matplotlib (>=3.6.1)"]
-postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"]
-spss = ["pyreadstat (>=1.1.2)"]
-sql-other = ["SQLAlchemy (>=1.4.16)"]
-test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"]
-xml = ["lxml (>=4.6.3)"]
-
-[[package]]
-name = "pandoc"
-version = "2.3"
-description = "Pandoc Documents for Python"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pandoc-2.3.tar.gz", hash = "sha256:e772c2c6d871146894579828dbaf1efd538eb64fc7e71d4a6b3a11a18baef90d"},
-]
-
-[package.dependencies]
-plumbum = "*"
-ply = "*"
-
-[[package]]
-name = "pcodedmp"
-version = "1.2.6"
-description = "A VBA p-code disassembler"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pcodedmp-1.2.6-py2.py3-none-any.whl", hash = "sha256:4441f7c0ab4cbda27bd4668db3b14f36261d86e5059ce06c0828602cbe1c4278"},
-    {file = "pcodedmp-1.2.6.tar.gz", hash = "sha256:025f8c809a126f45a082ffa820893e6a8d990d9d7ddb68694b5a9f0a6dbcd955"},
-]
-
-[package.dependencies]
-oletools = ">=0.54"
-win-unicode-console = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""}
-
-[[package]]
-name = "pdf2image"
-version = "1.16.3"
-description = "A wrapper around the pdftoppm and pdftocairo command line tools to convert PDF to a PIL Image list."
-optional = false
-python-versions = "*"
-files = [
-    {file = "pdf2image-1.16.3-py3-none-any.whl", hash = "sha256:b6154164af3677211c22cbb38b2bd778b43aca02758e962fe1e231f6d3b0e380"},
-    {file = "pdf2image-1.16.3.tar.gz", hash = "sha256:74208810c2cef4d9e347769b8e62a52303982ddb4f2dfd744c7ab4b940ae287e"},
-]
-
-[package.dependencies]
-pillow = "*"
-
-[[package]]
-name = "pdfminer-six"
-version = "20221105"
-description = "PDF parser and analyzer"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "pdfminer.six-20221105-py3-none-any.whl", hash = "sha256:1eaddd712d5b2732f8ac8486824533514f8ba12a0787b3d5fe1e686cd826532d"},
-    {file = "pdfminer.six-20221105.tar.gz", hash = "sha256:8448ab7b939d18b64820478ecac5394f482d7a79f5f7eaa7703c6c959c175e1d"},
-]
-
-[package.dependencies]
-charset-normalizer = ">=2.0.0"
-cryptography = ">=36.0.0"
-
-[package.extras]
-dev = ["black", "mypy (==0.931)", "nox", "pytest"]
-docs = ["sphinx", "sphinx-argparse"]
-image = ["Pillow"]
-
-[[package]]
-name = "pillow"
-version = "10.0.0"
-description = "Python Imaging Library (Fork)"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"},
-    {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"},
-    {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"},
-    {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"},
-    {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"},
-    {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"},
-    {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"},
-    {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"},
-    {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"},
-    {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"},
-    {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"},
-    {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"},
-    {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"},
-    {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"},
-    {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"},
-    {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"},
-    {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"},
-    {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"},
-    {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"},
-    {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"},
-    {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"},
-    {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"},
-    {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"},
-    {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"},
-    {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"},
-    {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"},
-    {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"},
-    {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"},
-    {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"},
-    {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"},
-    {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"},
-    {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"},
-    {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"},
-    {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"},
-    {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"},
-    {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"},
-    {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"},
-    {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"},
-    {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"},
-    {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"},
-    {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"},
-    {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"},
-    {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"},
-    {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"},
-    {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"},
-    {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"},
-    {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"},
-    {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"},
-    {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"},
-    {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"},
-    {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"},
-    {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"},
-    {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"},
-    {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"},
-    {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"},
-    {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"},
-]
-
-[package.extras]
-docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
-tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
-
-[[package]]
-name = "plumbum"
-version = "1.8.2"
-description = "Plumbum: shell combinators library"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "plumbum-1.8.2-py3-none-any.whl", hash = "sha256:3ad9e5f56c6ec98f6f7988f7ea8b52159662ea9e915868d369dbccbfca0e367e"},
-    {file = "plumbum-1.8.2.tar.gz", hash = "sha256:9e6dc032f4af952665f32f3206567bc23b7858b1413611afe603a3f8ad9bfd75"},
-]
-
-[package.dependencies]
-pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""}
-
-[package.extras]
-dev = ["paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"]
-docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"]
-ssh = ["paramiko"]
-
-[[package]]
-name = "ply"
-version = "3.11"
-description = "Python Lex & Yacc"
-optional = false
-python-versions = "*"
-files = [
-    {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"},
-    {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"},
-]
-
-[[package]]
-name = "posthog"
-version = "3.0.1"
-description = "Integrate PostHog into any python application."
-optional = false
-python-versions = "*"
-files = [
-    {file = "posthog-3.0.1-py2.py3-none-any.whl", hash = "sha256:9c7f92fecc713257d4b2710d05b456569c9156fbdd3e85655ba7ba5ba6c7b3ae"},
-    {file = "posthog-3.0.1.tar.gz", hash = "sha256:57d2791ff5752ce56ba0f9bb8876faf3ca9208f1c2c6ceaeb5a2504c34493767"},
-]
-
-[package.dependencies]
-backoff = ">=1.10.0"
-monotonic = ">=1.5"
-python-dateutil = ">2.1"
-requests = ">=2.7,<3.0"
-six = ">=1.5"
-
-[package.extras]
-dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"]
-sentry = ["django", "sentry-sdk"]
-test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest"]
-
-[[package]]
-name = "protobuf"
-version = "4.23.4"
-description = ""
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "protobuf-4.23.4-cp310-abi3-win32.whl", hash = "sha256:5fea3c64d41ea5ecf5697b83e41d09b9589e6f20b677ab3c48e5f242d9b7897b"},
-    {file = "protobuf-4.23.4-cp310-abi3-win_amd64.whl", hash = "sha256:7b19b6266d92ca6a2a87effa88ecc4af73ebc5cfde194dc737cf8ef23a9a3b12"},
-    {file = "protobuf-4.23.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8547bf44fe8cec3c69e3042f5c4fb3e36eb2a7a013bb0a44c018fc1e427aafbd"},
-    {file = "protobuf-4.23.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a"},
-    {file = "protobuf-4.23.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:effeac51ab79332d44fba74660d40ae79985901ac21bca408f8dc335a81aa597"},
-    {file = "protobuf-4.23.4-cp37-cp37m-win32.whl", hash = "sha256:c3e0939433c40796ca4cfc0fac08af50b00eb66a40bbbc5dee711998fb0bbc1e"},
-    {file = "protobuf-4.23.4-cp37-cp37m-win_amd64.whl", hash = "sha256:9053df6df8e5a76c84339ee4a9f5a2661ceee4a0dab019e8663c50ba324208b0"},
-    {file = "protobuf-4.23.4-cp38-cp38-win32.whl", hash = "sha256:e1c915778d8ced71e26fcf43c0866d7499891bca14c4368448a82edc61fdbc70"},
-    {file = "protobuf-4.23.4-cp38-cp38-win_amd64.whl", hash = "sha256:351cc90f7d10839c480aeb9b870a211e322bf05f6ab3f55fcb2f51331f80a7d2"},
-    {file = "protobuf-4.23.4-cp39-cp39-win32.whl", hash = "sha256:6dd9b9940e3f17077e820b75851126615ee38643c2c5332aa7a359988820c720"},
-    {file = "protobuf-4.23.4-cp39-cp39-win_amd64.whl", hash = "sha256:0a5759f5696895de8cc913f084e27fd4125e8fb0914bb729a17816a33819f474"},
-    {file = "protobuf-4.23.4-py3-none-any.whl", hash = "sha256:e9d0be5bf34b275b9f87ba7407796556abeeba635455d036c7351f7c183ef8ff"},
-    {file = "protobuf-4.23.4.tar.gz", hash = "sha256:ccd9430c0719dce806b93f89c91de7977304729e55377f872a92465d548329a9"},
-]
-
-[[package]]
-name = "pulsar-client"
-version = "3.2.0"
-description = "Apache Pulsar Python client library"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pulsar_client-3.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:da53bbe1903026ca1253d36a67bde0ae88513497091658aee8c5514c3e567483"},
-    {file = "pulsar_client-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec595a71b7a25f1a72a1350efd6680a511b53253c3cac1911ba3d6c4d71fa64c"},
-    {file = "pulsar_client-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3557c65463d74ec8d2864752389beb06761ab591dd134a164e0b1303c66719b"},
-    {file = "pulsar_client-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d51dc76fec48217489bde95754ad58288c9389361de42f5a27d64e19840d27fb"},
-    {file = "pulsar_client-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9ef2baf85311e0fe1b98342fdafbb93a1818a08ef999eaa524234fedf6f3b941"},
-    {file = "pulsar_client-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:0928b02beda0c98e77178f4e30e962ddb8ee8c3320e4c7304a78b0796e976523"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:584f44b03474a69906be711a597a4d516263a55be31e49fc07be503dc8406821"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a637b9a3b30860c61e68a7b8ea650e0987d89e82f73b6a3df1ab662a6438fdda"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4a187fdc5febcf16f725179dcf2c476f31eeebd8353794d91754a3202dd5072"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5ff879f868cf1fd29db99f39fdb22b3ec3e749c648aca28526689756d922d1c5"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a5f85d0cc414f739a5b51d843f213b54b2cd768c3a34f7c27cca410712b1f81"},
-    {file = "pulsar_client-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4fe748283848d829a80c0323558faeebea4c240d69fa58314ac90344f6999d17"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-macosx_10_15_universal2.whl", hash = "sha256:06b91c26def86dbbc35be15257999fd8a2afbadf32983916ea3eef44f4d4cab4"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39ec897bc8d232e6b118793378fc662a844334b829a28a1b4ad1c5fe8d019135"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa37c96c25c1b5aff3bad0fd0194b385ec190b2c67a2f439ac91577f81ae18d3"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d49cdd4d1b7fc2e80d100acf14e6fd3898f6e099e403fc56ed22a690245b2fec"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0058ca3191fd24528ccf94dba6f12e4093831454a2597166f96900d0717271bf"},
-    {file = "pulsar_client-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:cb69b0411008e0b56df51de0aab20aa1c1a12aef3019b9ceba89afbae1f07fe2"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:f7d33e99602352df7a30707eab4e5781654602212fb618928bffb5523f2bcf35"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad1ac15a175ca90555c681a4d0134568771c6346b97a172f3ef14006556a50ae"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369e08ef1d5cb196dd9271039928800f90b4701a9c9df90bc068b44260d2fb11"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a52ba2b6736a2ebeed31b590e75d417dda149e333461655860efa84d898a3eb4"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c801334b3b569b23976481a2922bcea0c6dd990fc26544658dd9e9c8f78ca36"},
-    {file = "pulsar_client-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cd01fd419280e9013d1655bc53662248be2656b623b1506480e1a985aa7dadd2"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:0abe54d84db76435a6cd88ce27610352cabc7efae9fa3e7f874e032ec2ca0b3f"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9a1b6a806eb4819d8cbab1c4ae44ebf2110a94204a46c365f5757e1455252f2"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34ea2a6b75ae0e303d522e5b57c75a4ff03dc18b9bfc14151fb14dfaf5866f17"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:be6d3a9b2e1db3b6d1a7db5e13f7b4ed420674cf072cdb520fb004c4cd54c0af"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6b733e6239ffb505f7084df0175baf9d0215f14d0a02e9bbd1fdf71a2d6ea17"},
-    {file = "pulsar_client-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:edc2135d02b4793efb086edca0ffaa6e8ac9133961c2cdc17ae487e0a53da481"},
-]
-
-[package.dependencies]
-certifi = "*"
-
-[package.extras]
-all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (==1.7.3)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
-avro = ["fastavro (==1.7.3)"]
-functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
-
-[[package]]
-name = "pycparser"
-version = "2.21"
-description = "C parser in Python"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
-    {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
-    {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
-]
-
-[[package]]
-name = "pydantic"
-version = "1.10.11"
-description = "Data validation and settings management using python type hints"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"},
-    {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"},
-    {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"},
-    {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"},
-    {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"},
-    {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"},
-    {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"},
-    {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"},
-    {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"},
-    {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"},
-    {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"},
-    {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"},
-    {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"},
-    {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"},
-    {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"},
-    {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"},
-    {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"},
-    {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"},
-    {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"},
-    {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"},
-    {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"},
-    {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"},
-    {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"},
-    {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"},
-    {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"},
-    {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"},
-    {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"},
-    {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"},
-    {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"},
-    {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"},
-    {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"},
-    {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"},
-    {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"},
-    {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"},
-    {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"},
-    {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"},
-]
-
-[package.dependencies]
-typing-extensions = ">=4.2.0"
-
-[package.extras]
-dotenv = ["python-dotenv (>=0.10.4)"]
-email = ["email-validator (>=1.0.3)"]
-
-[[package]]
-name = "pymupdf"
-version = "1.22.5"
-description = "Python bindings for the PDF toolkit and renderer MuPDF"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "PyMuPDF-1.22.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:640b8e4cb116dd87a3c854e49808a4f63625e663a7bc5b1efc971db5b4775367"},
-    {file = "PyMuPDF-1.22.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:17efbbf0e2d99d24cfc302fac512928eb294f10b7b67d597d04dafd012812e4e"},
-    {file = "PyMuPDF-1.22.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bc9b9bf0f2beea3911750d2d66247608be8cbad33b7a050cacec9e4c105a1ca"},
-    {file = "PyMuPDF-1.22.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7734a32a91eea4b502b8f9d2915cdba0a372226e14fb983876d763110dcefef"},
-    {file = "PyMuPDF-1.22.5-cp310-cp310-win32.whl", hash = "sha256:c2fd70ca9961f7871810dce1b7d0a42a69eb8ff2d786621123952bd505a6867e"},
-    {file = "PyMuPDF-1.22.5-cp310-cp310-win_amd64.whl", hash = "sha256:add310c96df6933cfb4ce3821c9c7b5c133e8aa609a4c9416e1c7af546163488"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:017aaba511526facfc928e9d95d2c10d28a2821b05b9039bf422031a7da8584e"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6fe5e44a14864d921fb96669a82f9635846806176f77f1d73c61feb84ebf4d84"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e74d766f79e41e10c51865233042ab2cc4612ca7942812dca0603f4d0f8f73d"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8175452fcc99a0af6429d8acd87682a3a70c5879d73532c7327f71ce508a35"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-win32.whl", hash = "sha256:42f59f4999d7f8b35c850050bd965e98c081a7d9b92d5f9dcf30203b30d06876"},
-    {file = "PyMuPDF-1.22.5-cp311-cp311-win_amd64.whl", hash = "sha256:3d71c47aa14b73f2df7d03be8c547a05df6c6898d8c63a0f752b26f206eefd3c"},
-    {file = "PyMuPDF-1.22.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4bcad7ea4b3ab82c46fe8da27ec738d38c213ed9935ef67d98ed09574d9a234e"},
-    {file = "PyMuPDF-1.22.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b04a83ddcb3f7c935c75a1f7f6050c85fe4062a2ea64c47ee6bda788d037761"},
-    {file = "PyMuPDF-1.22.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d02ee28663077f15d529b04d27588b174fa937daf73a294df279bbf70c468f5c"},
-    {file = "PyMuPDF-1.22.5-cp37-cp37m-win32.whl", hash = "sha256:411fc35f6dae16ec940b6b0406e84be6ff29f93b30908ea1427e2a4bd594d4ba"},
-    {file = "PyMuPDF-1.22.5-cp37-cp37m-win_amd64.whl", hash = "sha256:7c8c0f686865e330de90b93d53b100f7f07c2f10f5449ceb721121f459f7cc4a"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ae9f81b8fe0a3e6386a24887a92736793479c5918ecac3b7deac2d02abf1f2"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7562436dadf8382e59ac3739fbbf9d5b2d807fafc7f28cb884863430e0de6505"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c22046e5f2cf0d72f9809a967340db1b238fefe58322896bc7c3f3d1d10b42"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efa601dc4116c17a6b09255b031b5a1891e3ac18b50ec536452a725a6b75db8d"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-win32.whl", hash = "sha256:3d0fe749e648f5245059d5f771fb50c1a988a1d2e82268b56377b2176a9fee5d"},
-    {file = "PyMuPDF-1.22.5-cp38-cp38-win_amd64.whl", hash = "sha256:4fbc5bfe6ecc53929e3fd0db9846fb7da084ddb4b1fc1063857245fa783974d9"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:87b36e0797ab7fbb7ef594c7a6e0febc7ffb4101a42ea796726a8288391a3769"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:01119edb7e4c3dd8c154d237b8ac927bd359eea8d31468f9a89aa308b5bca04e"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde02fcb387863873b56730f4b9f65515d87c92c12299f0f0a74b3ccdfe35062"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30c55814bbf6461aef9b34cb524d1d14857d5ec6ccfbb78ecfb1d07dfc40eeb8"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-win32.whl", hash = "sha256:0542178c3a399282903705a8cc298e7f33f4770605e0a9db344aff5d375bcf0b"},
-    {file = "PyMuPDF-1.22.5-cp39-cp39-win_amd64.whl", hash = "sha256:f8ca46a6987e14f58ec8dfda2d2376bacd113c1fec5f58bebf90838bb4408ab9"},
-    {file = "PyMuPDF-1.22.5.tar.gz", hash = "sha256:5ec8d5106752297529d0d68d46cfc4ce99914aabd99be843f1599a1842d63fe9"},
-]
-
-[[package]]
-name = "pypandoc"
-version = "1.11"
-description = "Thin wrapper for pandoc."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "pypandoc-1.11-py3-none-any.whl", hash = "sha256:b260596934e9cfc6513056110a7c8600171d414f90558bf4407e68b209be8007"},
-    {file = "pypandoc-1.11.tar.gz", hash = "sha256:7f6d68db0e57e0f6961bec2190897118c4d305fc2d31c22cd16037f22ee084a5"},
-]
-
-[[package]]
-name = "pyparsing"
-version = "2.4.7"
-description = "Python parsing module"
-optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-files = [
-    {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
-    {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
-]
-
-[[package]]
-name = "pyreadline3"
-version = "3.4.1"
-description = "A python implementation of GNU readline."
-optional = false
-python-versions = "*"
-files = [
-    {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"},
-    {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"},
-]
-
-[[package]]
-name = "python-dateutil"
-version = "2.8.2"
-description = "Extensions to the standard Python datetime module"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
-files = [
-    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
-    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
-]
-
-[package.dependencies]
-six = ">=1.5"
-
-[[package]]
-name = "python-docx"
-version = "0.8.11"
-description = "Create and update Microsoft Word .docx files."
-optional = false
-python-versions = "*"
-files = [
-    {file = "python-docx-0.8.11.tar.gz", hash = "sha256:1105d233a0956dd8dd1e710d20b159e2d72ac3c301041b95f4d4ceb3e0ebebc4"},
-]
-
-[package.dependencies]
-lxml = ">=2.3.2"
-
-[[package]]
-name = "python-dotenv"
-version = "1.0.0"
-description = "Read key-value pairs from a .env file and set them as environment variables"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
-    {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
-]
-
-[package.extras]
-cli = ["click (>=5.0)"]
-
-[[package]]
-name = "python-magic"
-version = "0.4.27"
-description = "File type identification using libmagic"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-files = [
-    {file = "python-magic-0.4.27.tar.gz", hash = "sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b"},
-    {file = "python_magic-0.4.27-py2.py3-none-any.whl", hash = "sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"},
-]
-
-[[package]]
-name = "python-pptx"
-version = "0.6.21"
-description = "Generate and manipulate Open XML PowerPoint (.pptx) files"
-optional = false
-python-versions = "*"
-files = [
-    {file = "python-pptx-0.6.21.tar.gz", hash = "sha256:7798a2aaf89563565b3c7120c0acfe9aff775db0db3580544e3bf4840c2e378f"},
-]
-
-[package.dependencies]
-lxml = ">=3.1.0"
-Pillow = ">=3.3.2"
-XlsxWriter = ">=0.5.7"
-
-[[package]]
-name = "pytz"
-version = "2023.3"
-description = "World timezone definitions, modern and historical"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
-    {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
-]
-
-[[package]]
-name = "pywin32"
-version = "306"
-description = "Python for Window Extensions"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
-    {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
-    {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
-    {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
-    {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
-    {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
-    {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
-    {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
-    {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
-    {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
-    {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
-    {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
-    {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
-    {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
-]
-
-[[package]]
-name = "pyyaml"
-version = "6.0"
-description = "YAML parser and emitter for Python"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
-    {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
-    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
-    {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
-    {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
-    {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
-    {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
-    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
-    {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
-    {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
-    {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
-    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
-    {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
-    {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
-    {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
-    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
-    {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
-    {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
-    {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
-    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
-    {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
-    {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
-    {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
-    {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
-    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
-    {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
-    {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
-    {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
-]
-
-[[package]]
-name = "red-black-tree-mod"
-version = "1.20"
-description = "Flexible python implementation of red black trees"
-optional = false
-python-versions = "*"
-files = [
-    {file = "red-black-tree-mod-1.20.tar.gz", hash = "sha256:2448e6fc9cbf1be204c753f352c6ee49aa8156dbf1faa57dfc26bd7705077e0a"},
-]
-
-[[package]]
-name = "regex"
-version = "2023.6.3"
-description = "Alternative regular expression module, to replace re."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "regex-2023.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd"},
-    {file = "regex-2023.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d"},
-    {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536"},
-    {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2"},
-    {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222"},
-    {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2"},
-    {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18"},
-    {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568"},
-    {file = "regex-2023.6.3-cp310-cp310-win32.whl", hash = "sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1"},
-    {file = "regex-2023.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0"},
-    {file = "regex-2023.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969"},
-    {file = "regex-2023.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa"},
-    {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e"},
-    {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df"},
-    {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c"},
-    {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8"},
-    {file = "regex-2023.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9"},
-    {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c"},
-    {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7"},
-    {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f"},
-    {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461"},
-    {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477"},
-    {file = "regex-2023.6.3-cp311-cp311-win32.whl", hash = "sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9"},
-    {file = "regex-2023.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af"},
-    {file = "regex-2023.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14"},
-    {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f"},
-    {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e"},
-    {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3"},
-    {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1"},
-    {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1"},
-    {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787"},
-    {file = "regex-2023.6.3-cp36-cp36m-win32.whl", hash = "sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54"},
-    {file = "regex-2023.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27"},
-    {file = "regex-2023.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc"},
-    {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019"},
-    {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777"},
-    {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee"},
-    {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591"},
-    {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0"},
-    {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb"},
-    {file = "regex-2023.6.3-cp37-cp37m-win32.whl", hash = "sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7"},
-    {file = "regex-2023.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23"},
-    {file = "regex-2023.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07"},
-    {file = "regex-2023.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2"},
-    {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff"},
-    {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82"},
-    {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06"},
-    {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f"},
-    {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747"},
-    {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9"},
-    {file = "regex-2023.6.3-cp38-cp38-win32.whl", hash = "sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88"},
-    {file = "regex-2023.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72"},
-    {file = "regex-2023.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751"},
-    {file = "regex-2023.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77"},
-    {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9"},
-    {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd"},
-    {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938"},
-    {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7"},
-    {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac"},
-    {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd"},
-    {file = "regex-2023.6.3-cp39-cp39-win32.whl", hash = "sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f"},
-    {file = "regex-2023.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a"},
-    {file = "regex-2023.6.3.tar.gz", hash = "sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0"},
-]
-
-[[package]]
-name = "requests"
-version = "2.31.0"
-description = "Python HTTP for Humans."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
-    {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
-]
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<4"
-idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<3"
-
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
-
-[[package]]
-name = "rtfde"
-version = "0.0.2"
-description = "A library for extracting HTML content from RTF encapsulated HTML as commonly found in the exchange MSG email format."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "RTFDE-0.0.2-py3-none-any.whl", hash = "sha256:18386e4f060cee12a2a8035b0acf0cc99689f5dff1bf347bab7e92351860a21d"},
-    {file = "RTFDE-0.0.2.tar.gz", hash = "sha256:b86b5d734950fe8745a5b89133f50554252dbd67c6d1b9265e23ee140e7ea8a2"},
-]
-
-[package.dependencies]
-lark-parser = ">=0.11"
-oletools = ">=0.56"
-
-[package.extras]
-dev = ["lxml (>=4.6)"]
-msg-parse = ["extract-msg (>=0.27)"]
-
-[[package]]
-name = "safetensors"
-version = "0.3.2"
-description = "Fast and Safe Tensor serialization"
-optional = false
-python-versions = "*"
-files = [
-    {file = "safetensors-0.3.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b6a66989075c2891d743153e8ba9ca84ee7232c8539704488f454199b8b8f84d"},
-    {file = "safetensors-0.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:670d6bc3a3b377278ce2971fa7c36ebc0a35041c4ea23b9df750a39380800195"},
-    {file = "safetensors-0.3.2-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:564f42838721925b5313ae864ba6caa6f4c80a9fbe63cf24310c3be98ab013cd"},
-    {file = "safetensors-0.3.2-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:7f80af7e4ab3188daaff12d43d078da3017a90d732d38d7af4eb08b6ca2198a5"},
-    {file = "safetensors-0.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec30d78f20f1235b252d59cbb9755beb35a1fde8c24c89b3c98e6a1804cfd432"},
-    {file = "safetensors-0.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16063d94d8f600768d3c331b1e97964b1bf3772e19710105fe24ec5a6af63770"},
-    {file = "safetensors-0.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb44e140bf2aeda98d9dde669dbec15f7b77f96a9274469b91a6cf4bcc5ec3b"},
-    {file = "safetensors-0.3.2-cp310-cp310-win32.whl", hash = "sha256:2961c1243fd0da46aa6a1c835305cc4595486f8ac64632a604d0eb5f2de76175"},
-    {file = "safetensors-0.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c813920482c337d1424d306e1b05824a38e3ef94303748a0a287dea7a8c4f805"},
-    {file = "safetensors-0.3.2-cp311-cp311-macosx_10_11_universal2.whl", hash = "sha256:707df34bd9b9047e97332136ad98e57028faeccdb9cfe1c3b52aba5964cc24bf"},
-    {file = "safetensors-0.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:becc5bb85b2947eae20ed23b407ebfd5277d9a560f90381fe2c42e6c043677ba"},
-    {file = "safetensors-0.3.2-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:30a75707be5cc9686490bde14b9a371cede4af53244ea72b340cfbabfffdf58a"},
-    {file = "safetensors-0.3.2-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:54ad6af663e15e2b99e2ea3280981b7514485df72ba6d014dc22dae7ba6a5e6c"},
-    {file = "safetensors-0.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37764b3197656ef507a266c453e909a3477dabc795962b38e3ad28226f53153b"},
-    {file = "safetensors-0.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4939067736783acd8391d83cd97d6c202f94181951ce697d519f9746381b6a39"},
-    {file = "safetensors-0.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada0fac127ff8fb04834da5c6d85a8077e6a1c9180a11251d96f8068db922a17"},
-    {file = "safetensors-0.3.2-cp311-cp311-win32.whl", hash = "sha256:155b82dbe2b0ebff18cde3f76b42b6d9470296e92561ef1a282004d449fa2b4c"},
-    {file = "safetensors-0.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:a86428d196959619ce90197731be9391b5098b35100a7228ef4643957648f7f5"},
-    {file = "safetensors-0.3.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:c1f8ab41ed735c5b581f451fd15d9602ff51aa88044bfa933c5fa4b1d0c644d1"},
-    {file = "safetensors-0.3.2-cp37-cp37m-macosx_13_0_x86_64.whl", hash = "sha256:bc9cfb3c9ea2aec89685b4d656f9f2296f0f0d67ecf2bebf950870e3be89b3db"},
-    {file = "safetensors-0.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ace5d471e3d78e0d93f952707d808b5ab5eac77ddb034ceb702e602e9acf2be9"},
-    {file = "safetensors-0.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de3e20a388b444381bcda1a3193cce51825ddca277e4cf3ed1fe8d9b2d5722cd"},
-    {file = "safetensors-0.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d7d70d48585fe8df00725aa788f2e64fd24a4c9ae07cd6be34f6859d0f89a9c"},
-    {file = "safetensors-0.3.2-cp37-cp37m-win32.whl", hash = "sha256:6ff59bc90cdc857f68b1023be9085fda6202bbe7f2fd67d06af8f976d6adcc10"},
-    {file = "safetensors-0.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8b05c93da15fa911763a89281906ca333ed800ab0ef1c7ce53317aa1a2322f19"},
-    {file = "safetensors-0.3.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:8969cfd9e8d904e8d3c67c989e1bd9a95e3cc8980d4f95e4dcd43c299bb94253"},
-    {file = "safetensors-0.3.2-cp38-cp38-macosx_13_0_x86_64.whl", hash = "sha256:f54148ac027556eb02187e9bc1556c4d916c99ca3cb34ca36a7d304d675035c1"},
-    {file = "safetensors-0.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caec25fedbcf73f66c9261984f07885680f71417fc173f52279276c7f8a5edd3"},
-    {file = "safetensors-0.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50224a1d99927ccf3b75e27c3d412f7043280431ab100b4f08aad470c37cf99a"},
-    {file = "safetensors-0.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa98f49e95f02eb750d32c4947e7d5aa43883149ebd0414920866446525b70f0"},
-    {file = "safetensors-0.3.2-cp38-cp38-win32.whl", hash = "sha256:33409df5e28a83dc5cc5547a3ac17c0f1b13a1847b1eb3bc4b3be0df9915171e"},
-    {file = "safetensors-0.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:e04a7cbbb3856159ab99e3adb14521544f65fcb8548cce773a1435a0f8d78d27"},
-    {file = "safetensors-0.3.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:7c864cf5dcbfb608c5378f83319c60cc9c97263343b57c02756b7613cd5ab4dd"},
-    {file = "safetensors-0.3.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:14e8c19d6dc51d4f70ee33c46aff04c8ba3f95812e74daf8036c24bc86e75cae"},
-    {file = "safetensors-0.3.2-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:042a60f633c3c7009fdf6a7c182b165cb7283649d2a1e9c7a4a1c23454bd9a5b"},
-    {file = "safetensors-0.3.2-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:fafd95e5ef41e8f312e2a32b7031f7b9b2a621b255f867b221f94bb2e9f51ae8"},
-    {file = "safetensors-0.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ed77cf358abce2307f03634694e0b2a29822e322a1623e0b1aa4b41e871bf8b"},
-    {file = "safetensors-0.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d344e8b2681a33aafc197c90b0def3229b3317d749531c72fa6259d0caa5c8c"},
-    {file = "safetensors-0.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87ff0024ef2e5722a79af24688ce4a430f70601d0cf712a744105ed4b8f67ba5"},
-    {file = "safetensors-0.3.2-cp39-cp39-win32.whl", hash = "sha256:827af9478b78977248ba93e2fd97ea307fb63f463f80cef4824460f8c2542a52"},
-    {file = "safetensors-0.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9b09f27c456efa301f98681ea14b12f81f2637889f6336223ccab71e42c34541"},
-    {file = "safetensors-0.3.2.tar.gz", hash = "sha256:2dbd34554ed3b99435a0e84df077108f5334c8336b5ed9cb8b6b98f7b10da2f6"},
-]
-
-[package.extras]
-all = ["black (==22.3)", "click (==8.0.4)", "flake8 (>=3.8.3)", "flax (>=0.6.3)", "h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "isort (>=5.5.4)", "jax (>=0.3.25)", "jaxlib (>=0.3.25)", "numpy (>=1.21.6)", "paddlepaddle (>=2.4.1)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "setuptools-rust (>=1.5.2)", "tensorflow (==2.11.0)", "torch (>=1.10)"]
-dev = ["black (==22.3)", "click (==8.0.4)", "flake8 (>=3.8.3)", "flax (>=0.6.3)", "h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "isort (>=5.5.4)", "jax (>=0.3.25)", "jaxlib (>=0.3.25)", "numpy (>=1.21.6)", "paddlepaddle (>=2.4.1)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "setuptools-rust (>=1.5.2)", "tensorflow (==2.11.0)", "torch (>=1.10)"]
-jax = ["flax (>=0.6.3)", "jax (>=0.3.25)", "jaxlib (>=0.3.25)"]
-numpy = ["numpy (>=1.21.6)"]
-paddlepaddle = ["paddlepaddle (>=2.4.1)"]
-pinned-tf = ["tensorflow (==2.11.0)"]
-quality = ["black (==22.3)", "click (==8.0.4)", "flake8 (>=3.8.3)", "isort (>=5.5.4)"]
-tensorflow = ["tensorflow (>=2.11.0)"]
-testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "numpy (>=1.21.6)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "setuptools-rust (>=1.5.2)"]
-torch = ["torch (>=1.10)"]
-
-[[package]]
-name = "scikit-learn"
-version = "1.3.0"
-description = "A set of python modules for machine learning and data mining"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "scikit-learn-1.3.0.tar.gz", hash = "sha256:8be549886f5eda46436b6e555b0e4873b4f10aa21c07df45c4bc1735afbccd7a"},
-    {file = "scikit_learn-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:981287869e576d42c682cf7ca96af0c6ac544ed9316328fd0d9292795c742cf5"},
-    {file = "scikit_learn-1.3.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:436aaaae2c916ad16631142488e4c82f4296af2404f480e031d866863425d2a2"},
-    {file = "scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7e28d8fa47a0b30ae1bd7a079519dd852764e31708a7804da6cb6f8b36e3630"},
-    {file = "scikit_learn-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae80c08834a473d08a204d966982a62e11c976228d306a2648c575e3ead12111"},
-    {file = "scikit_learn-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:552fd1b6ee22900cf1780d7386a554bb96949e9a359999177cf30211e6b20df6"},
-    {file = "scikit_learn-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79970a6d759eb00a62266a31e2637d07d2d28446fca8079cf9afa7c07b0427f8"},
-    {file = "scikit_learn-1.3.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:850a00b559e636b23901aabbe79b73dc604b4e4248ba9e2d6e72f95063765603"},
-    {file = "scikit_learn-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee04835fb016e8062ee9fe9074aef9b82e430504e420bff51e3e5fffe72750ca"},
-    {file = "scikit_learn-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d953531f5d9f00c90c34fa3b7d7cfb43ecff4c605dac9e4255a20b114a27369"},
-    {file = "scikit_learn-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:151ac2bf65ccf363664a689b8beafc9e6aae36263db114b4ca06fbbbf827444a"},
-    {file = "scikit_learn-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a885a9edc9c0a341cab27ec4f8a6c58b35f3d449c9d2503a6fd23e06bbd4f6a"},
-    {file = "scikit_learn-1.3.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:9877af9c6d1b15486e18a94101b742e9d0d2f343d35a634e337411ddb57783f3"},
-    {file = "scikit_learn-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c470f53cea065ff3d588050955c492793bb50c19a92923490d18fcb637f6383a"},
-    {file = "scikit_learn-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd6e2d7389542eae01077a1ee0318c4fec20c66c957f45c7aac0c6eb0fe3c612"},
-    {file = "scikit_learn-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:3a11936adbc379a6061ea32fa03338d4ca7248d86dd507c81e13af428a5bc1db"},
-    {file = "scikit_learn-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:998d38fcec96584deee1e79cd127469b3ad6fefd1ea6c2dfc54e8db367eb396b"},
-    {file = "scikit_learn-1.3.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:ded35e810438a527e17623ac6deae3b360134345b7c598175ab7741720d7ffa7"},
-    {file = "scikit_learn-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e8102d5036e28d08ab47166b48c8d5e5810704daecf3a476a4282d562be9a28"},
-    {file = "scikit_learn-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7617164951c422747e7c32be4afa15d75ad8044f42e7d70d3e2e0429a50e6718"},
-    {file = "scikit_learn-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:1d54fb9e6038284548072df22fd34777e434153f7ffac72c8596f2d6987110dd"},
-]
-
-[package.dependencies]
-joblib = ">=1.1.1"
-numpy = ">=1.17.3"
-scipy = ">=1.5.0"
-threadpoolctl = ">=2.0.0"
-
-[package.extras]
-benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"]
-docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.10.1)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"]
-examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"]
-tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.16.2)"]
-
-[[package]]
-name = "scipy"
-version = "1.9.3"
-description = "Fundamental algorithms for scientific computing in Python"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"},
-    {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"},
-    {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"},
-    {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"},
-    {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"},
-    {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"},
-    {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"},
-    {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"},
-    {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"},
-    {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"},
-    {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"},
-    {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"},
-    {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"},
-    {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"},
-    {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"},
-    {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"},
-    {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"},
-    {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"},
-    {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"},
-    {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"},
-    {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"},
-]
-
-[package.dependencies]
-numpy = ">=1.18.5,<1.26.0"
-
-[package.extras]
-dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"]
-doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"]
-test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
-
-[[package]]
-name = "sentence-transformers"
-version = "2.2.2"
-description = "Multilingual text embeddings"
-optional = false
-python-versions = ">=3.6.0"
-files = [
-    {file = "sentence-transformers-2.2.2.tar.gz", hash = "sha256:dbc60163b27de21076c9a30d24b5b7b6fa05141d68cf2553fa9a77bf79a29136"},
-]
-
-[package.dependencies]
-huggingface-hub = ">=0.4.0"
-nltk = "*"
-numpy = "*"
-scikit-learn = "*"
-scipy = "*"
-sentencepiece = "*"
-torch = ">=1.6.0"
-torchvision = "*"
-tqdm = "*"
-transformers = ">=4.6.0,<5.0.0"
-
-[[package]]
-name = "sentencepiece"
-version = "0.1.99"
-description = "SentencePiece python wrapper"
-optional = false
-python-versions = "*"
-files = [
-    {file = "sentencepiece-0.1.99-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0eb528e70571b7c02723e5804322469b82fe7ea418c96051d0286c0fa028db73"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77d7fafb2c4e4659cbdf303929503f37a26eabc4ff31d3a79bf1c5a1b338caa7"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be9cf5b9e404c245aeb3d3723c737ba7a8f5d4ba262ef233a431fa6c45f732a0"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baed1a26464998f9710d20e52607c29ffd4293e7c71c6a1f83f51ad0911ec12c"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9832f08bb372d4c8b567612f8eab9e36e268dff645f1c28f9f8e851be705f6d1"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:019e7535108e309dae2b253a75834fc3128240aa87c00eb80732078cdc182588"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-win32.whl", hash = "sha256:fa16a830416bb823fa2a52cbdd474d1f7f3bba527fd2304fb4b140dad31bb9bc"},
-    {file = "sentencepiece-0.1.99-cp310-cp310-win_amd64.whl", hash = "sha256:14b0eccb7b641d4591c3e12ae44cab537d68352e4d3b6424944f0c447d2348d5"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6d3c56f24183a1e8bd61043ff2c58dfecdc68a5dd8955dc13bab83afd5f76b81"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed6ea1819fd612c989999e44a51bf556d0ef6abfb553080b9be3d347e18bcfb7"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2a0260cd1fb7bd8b4d4f39dc2444a8d5fd4e0a0c4d5c899810ef1abf99b2d45"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a1abff4d1ff81c77cac3cc6fefa34fa4b8b371e5ee51cb7e8d1ebc996d05983"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:004e6a621d4bc88978eecb6ea7959264239a17b70f2cbc348033d8195c9808ec"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db361e03342c41680afae5807590bc88aa0e17cfd1a42696a160e4005fcda03b"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-win32.whl", hash = "sha256:2d95e19168875b70df62916eb55428a0cbcb834ac51d5a7e664eda74def9e1e0"},
-    {file = "sentencepiece-0.1.99-cp311-cp311-win_amd64.whl", hash = "sha256:f90d73a6f81248a909f55d8e6ef56fec32d559e1e9af045f0b0322637cb8e5c7"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:62e24c81e74bd87a6e0d63c51beb6527e4c0add67e1a17bac18bcd2076afcfeb"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57efcc2d51caff20d9573567d9fd3f854d9efe613ed58a439c78c9f93101384a"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a904c46197993bd1e95b93a6e373dca2f170379d64441041e2e628ad4afb16f"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d89adf59854741c0d465f0e1525b388c0d174f611cc04af54153c5c4f36088c4"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-win32.whl", hash = "sha256:47c378146928690d1bc106fdf0da768cebd03b65dd8405aa3dd88f9c81e35dba"},
-    {file = "sentencepiece-0.1.99-cp36-cp36m-win_amd64.whl", hash = "sha256:9ba142e7a90dd6d823c44f9870abdad45e6c63958eb60fe44cca6828d3b69da2"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b7b1a9ae4d7c6f1f867e63370cca25cc17b6f4886729595b885ee07a58d3cec3"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0f644c9d4d35c096a538507b2163e6191512460035bf51358794a78515b74f7"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8843d23a0f686d85e569bd6dcd0dd0e0cbc03731e63497ca6d5bacd18df8b85"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e6f690a1caebb4867a2e367afa1918ad35be257ecdb3455d2bbd787936f155"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-win32.whl", hash = "sha256:8a321866c2f85da7beac74a824b4ad6ddc2a4c9bccd9382529506d48f744a12c"},
-    {file = "sentencepiece-0.1.99-cp37-cp37m-win_amd64.whl", hash = "sha256:c42f753bcfb7661c122a15b20be7f684b61fc8592c89c870adf52382ea72262d"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:85b476406da69c70586f0bb682fcca4c9b40e5059814f2db92303ea4585c650c"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cfbcfe13c69d3f87b7fcd5da168df7290a6d006329be71f90ba4f56bc77f8561"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:445b0ec381af1cd4eef95243e7180c63d9c384443c16c4c47a28196bd1cda937"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6890ea0f2b4703f62d0bf27932e35808b1f679bdb05c7eeb3812b935ba02001"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb71af492b0eefbf9f2501bec97bcd043b6812ab000d119eaf4bd33f9e283d03"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27b866b5bd3ddd54166bbcbf5c8d7dd2e0b397fac8537991c7f544220b1f67bc"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-win32.whl", hash = "sha256:b133e8a499eac49c581c3c76e9bdd08c338cc1939e441fee6f92c0ccb5f1f8be"},
-    {file = "sentencepiece-0.1.99-cp38-cp38-win_amd64.whl", hash = "sha256:0eaf3591dd0690a87f44f4df129cf8d05d8a4029b5b6709b489b8e27f9a9bcff"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38efeda9bbfb55052d482a009c6a37e52f42ebffcea9d3a98a61de7aee356a28"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c030b081dc1e1bcc9fadc314b19b740715d3d566ad73a482da20d7d46fd444c"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84dbe53e02e4f8a2e45d2ac3e430d5c83182142658e25edd76539b7648928727"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b0f55d0a0ee1719b4b04221fe0c9f0c3461dc3dabd77a035fa2f4788eb3ef9a"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e800f206cd235dc27dc749299e05853a4e4332e8d3dfd81bf13d0e5b9007d9"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ae1c40cda8f9d5b0423cfa98542735c0235e7597d79caf318855cdf971b2280"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-win32.whl", hash = "sha256:c84ce33af12ca222d14a1cdd37bd76a69401e32bc68fe61c67ef6b59402f4ab8"},
-    {file = "sentencepiece-0.1.99-cp39-cp39-win_amd64.whl", hash = "sha256:350e5c74d739973f1c9643edb80f7cc904dc948578bcb1d43c6f2b173e5d18dd"},
-    {file = "sentencepiece-0.1.99.tar.gz", hash = "sha256:189c48f5cb2949288f97ccdb97f0473098d9c3dcf5a3d99d4eabe719ec27297f"},
-]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-files = [
-    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
-    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-
-[[package]]
-name = "sniffio"
-version = "1.3.0"
-description = "Sniff out which async library your code is running under"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
-    {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
-]
-
-[[package]]
-name = "soupsieve"
-version = "2.4.1"
-description = "A modern CSS selector implementation for Beautiful Soup."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"},
-    {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"},
-]
-
-[[package]]
-name = "sqlalchemy"
-version = "2.0.18"
-description = "Database Abstraction Library"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ddd6d35c598af872f9a0a5bce7f7c4a1841684a72dab3302e3df7f17d1b5249"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:00aa050faf24ce5f2af643e2b86822fa1d7149649995f11bc1e769bbfbf9010b"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b52c6741073de5a744d27329f9803938dcad5c9fee7e61690c705f72973f4175"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7db97eabd440327c35b751d5ebf78a107f505586485159bcc87660da8bb1fdca"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:589aba9a35869695b319ed76c6f673d896cd01a7ff78054be1596df7ad9b096f"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9da4ee8f711e077633730955c8f3cd2485c9abf5ea0f80aac23221a3224b9a8c"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-win32.whl", hash = "sha256:5dd574a37be388512c72fe0d7318cb8e31743a9b2699847a025e0c08c5bf579d"},
-    {file = "SQLAlchemy-2.0.18-cp310-cp310-win_amd64.whl", hash = "sha256:6852cd34d96835e4c9091c1e6087325efb5b607b75fd9f7075616197d1c4688a"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10e001a84f820fea2640e4500e12322b03afc31d8f4f6b813b44813b2a7c7e0d"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bffd6cd47c2e68970039c0d3e355c9ed761d3ca727b204e63cd294cad0e3df90"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b7b3ebfa9416c8eafaffa65216e229480c495e305a06ba176dcac32710744e6"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79228a7b90d95957354f37b9d46f2cc8926262ae17b0d3ed8f36c892f2a37e06"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ba633b51835036ff0f402c21f3ff567c565a22ff0a5732b060a68f4660e2a38f"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8da677135eff43502b7afab5a1e641edfb2dc734ba7fc146e9b1b86817a728e2"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-win32.whl", hash = "sha256:82edf3a6090554a83942cec79151d6b5eb96e63d143e80e4cf6671e5d772f6be"},
-    {file = "SQLAlchemy-2.0.18-cp311-cp311-win_amd64.whl", hash = "sha256:69ae0e9509c43474e33152abe1385b8954922544616426bf793481e1a37e094f"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:09397a18733fa2a4c7680b746094f980060666ee549deafdb5e102a99ce4619b"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45b07470571bda5ee7f5ec471271bbde97267cc8403fce05e280c36ea73f4754"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1aac42a21a7fa6c9665392c840b295962992ddf40aecf0a88073bc5c76728117"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:da46beef0ce882546d92b7b2e8deb9e04dbb8fec72945a8eb28b347ca46bc15a"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a6f1d8256d06f58e6ece150fbe05c63c7f9510df99ee8ac37423f5476a2cebb4"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-win32.whl", hash = "sha256:67fbb40db3985c0cfb942fe8853ad94a5e9702d2987dec03abadc2f3b6a24afb"},
-    {file = "SQLAlchemy-2.0.18-cp37-cp37m-win_amd64.whl", hash = "sha256:afb322ca05e2603deedbcd2e9910f11a3fd2f42bdeafe63018e5641945c7491c"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:908c850b98cac1e203ababd4ba76868d19ae0d7172cdc75d3f1b7829b16837d2"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10514adc41fc8f5922728fbac13d401a1aefcf037f009e64ca3b92464e33bf0e"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b791577c546b6bbd7b43953565fcb0a2fec63643ad605353dd48afbc3c48317"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:420bc6d06d4ae7fb6921524334689eebcbea7bf2005efef070a8562cc9527a37"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ebdd2418ab4e2e26d572d9a1c03877f8514a9b7436729525aa571862507b3fea"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:556dc18e39b6edb76239acfd1c010e37395a54c7fde8c57481c15819a3ffb13e"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-win32.whl", hash = "sha256:7b8cba5a25e95041e3413d91f9e50616bcfaec95afa038ce7dc02efefe576745"},
-    {file = "SQLAlchemy-2.0.18-cp38-cp38-win_amd64.whl", hash = "sha256:0f7fdcce52cd882b559a57b484efc92e108efeeee89fab6b623aba1ac68aad2e"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d7a2c1e711ce59ac9d0bba780318bcd102d2958bb423209f24c6354d8c4da930"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c95e3e7cc6285bf7ff263eabb0d3bfe3def9a1ff98124083d45e5ece72f4579"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc44e50f9d5e96af1a561faa36863f9191f27364a4df3eb70bca66e9370480b6"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfa1a0f83bdf8061db8d17c2029454722043f1e4dd1b3d3d3120d1b54e75825a"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:194f2d5a7cb3739875c4d25b3fe288ab0b3dc33f7c857ba2845830c8c51170a0"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ebc542d2289c0b016d6945fd07a7e2e23f4abc41e731ac8ad18a9e0c2fd0ec2"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-win32.whl", hash = "sha256:774bd401e7993452ba0596e741c0c4d6d22f882dd2a798993859181dbffadc62"},
-    {file = "SQLAlchemy-2.0.18-cp39-cp39-win_amd64.whl", hash = "sha256:2756485f49e7df5c2208bdc64263d19d23eba70666f14ad12d6d8278a2fff65f"},
-    {file = "SQLAlchemy-2.0.18-py3-none-any.whl", hash = "sha256:6c5bae4c288bda92a7550fe8de9e068c0a7cd56b1c5d888aae5b40f0e13b40bd"},
-    {file = "SQLAlchemy-2.0.18.tar.gz", hash = "sha256:1fb792051db66e09c200e7bc3bda3b1eb18a5b8eb153d2cedb2b14b56a68b8cb"},
-]
-
-[package.dependencies]
-greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""}
-typing-extensions = ">=4.2.0"
-
-[package.extras]
-aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
-aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
-asyncio = ["greenlet (!=0.4.17)"]
-asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
-mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
-mssql = ["pyodbc"]
-mssql-pymssql = ["pymssql"]
-mssql-pyodbc = ["pyodbc"]
-mypy = ["mypy (>=0.910)"]
-mysql = ["mysqlclient (>=1.4.0)"]
-mysql-connector = ["mysql-connector-python"]
-oracle = ["cx-oracle (>=7)"]
-oracle-oracledb = ["oracledb (>=1.0.1)"]
-postgresql = ["psycopg2 (>=2.7)"]
-postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
-postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
-postgresql-psycopg = ["psycopg (>=3.0.7)"]
-postgresql-psycopg2binary = ["psycopg2-binary"]
-postgresql-psycopg2cffi = ["psycopg2cffi"]
-postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
-pymysql = ["pymysql"]
-sqlcipher = ["sqlcipher3-binary"]
-
-[[package]]
-name = "starlette"
-version = "0.27.0"
-description = "The little ASGI library that shines."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
-    {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
-]
-
-[package.dependencies]
-anyio = ">=3.4.0,<5"
-
-[package.extras]
-full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
-
-[[package]]
-name = "sympy"
-version = "1.12"
-description = "Computer algebra system (CAS) in Python"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"},
-    {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"},
-]
-
-[package.dependencies]
-mpmath = ">=0.19"
-
-[[package]]
-name = "tabulate"
-version = "0.9.0"
-description = "Pretty-print tabular data"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
-    {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
-]
-
-[package.extras]
-widechars = ["wcwidth"]
-
-[[package]]
-name = "tenacity"
-version = "8.2.2"
-description = "Retry code until it succeeds"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"},
-    {file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"},
-]
-
-[package.extras]
-doc = ["reno", "sphinx", "tornado (>=4.5)"]
-
-[[package]]
-name = "threadpoolctl"
-version = "3.2.0"
-description = "threadpoolctl"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"},
-    {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"},
-]
-
-[[package]]
-name = "tokenizers"
-version = "0.13.3"
-description = "Fast and Customizable Tokenizers"
-optional = false
-python-versions = "*"
-files = [
-    {file = "tokenizers-0.13.3-cp310-cp310-macosx_10_11_x86_64.whl", hash = "sha256:f3835c5be51de8c0a092058a4d4380cb9244fb34681fd0a295fbf0a52a5fdf33"},
-    {file = "tokenizers-0.13.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4ef4c3e821730f2692489e926b184321e887f34fb8a6b80b8096b966ba663d07"},
-    {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5fd1a6a25353e9aa762e2aae5a1e63883cad9f4e997c447ec39d071020459bc"},
-    {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee0b1b311d65beab83d7a41c56a1e46ab732a9eed4460648e8eb0bd69fc2d059"},
-    {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ef4215284df1277dadbcc5e17d4882bda19f770d02348e73523f7e7d8b8d396"},
-    {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4d53976079cff8a033f778fb9adca2d9d69d009c02fa2d71a878b5f3963ed30"},
-    {file = "tokenizers-0.13.3-cp310-cp310-win32.whl", hash = "sha256:1f0e3b4c2ea2cd13238ce43548959c118069db7579e5d40ec270ad77da5833ce"},
-    {file = "tokenizers-0.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:89649c00d0d7211e8186f7a75dfa1db6996f65edce4b84821817eadcc2d3c79e"},
-    {file = "tokenizers-0.13.3-cp311-cp311-macosx_10_11_universal2.whl", hash = "sha256:56b726e0d2bbc9243872b0144515ba684af5b8d8cd112fb83ee1365e26ec74c8"},
-    {file = "tokenizers-0.13.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:cc5c022ce692e1f499d745af293ab9ee6f5d92538ed2faf73f9708c89ee59ce6"},
-    {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55c981ac44ba87c93e847c333e58c12abcbb377a0c2f2ef96e1a266e4184ff2"},
-    {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f247eae99800ef821a91f47c5280e9e9afaeed9980fc444208d5aa6ba69ff148"},
-    {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b3e3215d048e94f40f1c95802e45dcc37c5b05eb46280fc2ccc8cd351bff839"},
-    {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ba2b0bf01777c9b9bc94b53764d6684554ce98551fec496f71bc5be3a03e98b"},
-    {file = "tokenizers-0.13.3-cp311-cp311-win32.whl", hash = "sha256:cc78d77f597d1c458bf0ea7c2a64b6aa06941c7a99cb135b5969b0278824d808"},
-    {file = "tokenizers-0.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:ecf182bf59bd541a8876deccf0360f5ae60496fd50b58510048020751cf1724c"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:0527dc5436a1f6bf2c0327da3145687d3bcfbeab91fed8458920093de3901b44"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07cbb2c307627dc99b44b22ef05ff4473aa7c7cc1fec8f0a8b37d8a64b1a16d2"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4560dbdeaae5b7ee0d4e493027e3de6d53c991b5002d7ff95083c99e11dd5ac0"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64064bd0322405c9374305ab9b4c07152a1474370327499911937fd4a76d004b"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8c6e2ab0f2e3d939ca66aa1d596602105fe33b505cd2854a4c1717f704c51de"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-win32.whl", hash = "sha256:6cc29d410768f960db8677221e497226e545eaaea01aa3613fa0fdf2cc96cff4"},
-    {file = "tokenizers-0.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fc2a7fdf864554a0dacf09d32e17c0caa9afe72baf9dd7ddedc61973bae352d8"},
-    {file = "tokenizers-0.13.3-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:8791dedba834c1fc55e5f1521be325ea3dafb381964be20684b92fdac95d79b7"},
-    {file = "tokenizers-0.13.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:d607a6a13718aeb20507bdf2b96162ead5145bbbfa26788d6b833f98b31b26e1"},
-    {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3791338f809cd1bf8e4fee6b540b36822434d0c6c6bc47162448deee3f77d425"},
-    {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2f35f30e39e6aab8716f07790f646bdc6e4a853816cc49a95ef2a9016bf9ce6"},
-    {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310204dfed5aa797128b65d63538a9837cbdd15da2a29a77d67eefa489edda26"},
-    {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0f9b92ea052305166559f38498b3b0cae159caea712646648aaa272f7160963"},
-    {file = "tokenizers-0.13.3-cp38-cp38-win32.whl", hash = "sha256:9a3fa134896c3c1f0da6e762d15141fbff30d094067c8f1157b9fdca593b5806"},
-    {file = "tokenizers-0.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:8e7b0cdeace87fa9e760e6a605e0ae8fc14b7d72e9fc19c578116f7287bb873d"},
-    {file = "tokenizers-0.13.3-cp39-cp39-macosx_10_11_x86_64.whl", hash = "sha256:00cee1e0859d55507e693a48fa4aef07060c4bb6bd93d80120e18fea9371c66d"},
-    {file = "tokenizers-0.13.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:a23ff602d0797cea1d0506ce69b27523b07e70f6dda982ab8cf82402de839088"},
-    {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ce07445050b537d2696022dafb115307abdffd2a5c106f029490f84501ef97"},
-    {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:280ffe95f50eaaf655b3a1dc7ff1d9cf4777029dbbc3e63a74e65a056594abc3"},
-    {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97acfcec592f7e9de8cadcdcda50a7134423ac8455c0166b28c9ff04d227b371"},
-    {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7730c98a3010cd4f523465867ff95cd9d6430db46676ce79358f65ae39797b"},
-    {file = "tokenizers-0.13.3-cp39-cp39-win32.whl", hash = "sha256:48625a108029cb1ddf42e17a81b5a3230ba6888a70c9dc14e81bc319e812652d"},
-    {file = "tokenizers-0.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:bc0a6f1ba036e482db6453571c9e3e60ecd5489980ffd95d11dc9f960483d783"},
-    {file = "tokenizers-0.13.3.tar.gz", hash = "sha256:2e546dbb68b623008a5442353137fbb0123d311a6d7ba52f2667c8862a75af2e"},
-]
-
-[package.extras]
-dev = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"]
-docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"]
-testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"]
-
-[[package]]
-name = "torch"
-version = "2.0.1"
-description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration"
-optional = false
-python-versions = ">=3.8.0"
-files = [
-    {file = "torch-2.0.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:8ced00b3ba471856b993822508f77c98f48a458623596a4c43136158781e306a"},
-    {file = "torch-2.0.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:359bfaad94d1cda02ab775dc1cc386d585712329bb47b8741607ef6ef4950747"},
-    {file = "torch-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:7c84e44d9002182edd859f3400deaa7410f5ec948a519cc7ef512c2f9b34d2c4"},
-    {file = "torch-2.0.1-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:567f84d657edc5582d716900543e6e62353dbe275e61cdc36eda4929e46df9e7"},
-    {file = "torch-2.0.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:787b5a78aa7917465e9b96399b883920c88a08f4eb63b5a5d2d1a16e27d2f89b"},
-    {file = "torch-2.0.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:e617b1d0abaf6ced02dbb9486803abfef0d581609b09641b34fa315c9c40766d"},
-    {file = "torch-2.0.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b6019b1de4978e96daa21d6a3ebb41e88a0b474898fe251fd96189587408873e"},
-    {file = "torch-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:dbd68cbd1cd9da32fe5d294dd3411509b3d841baecb780b38b3b7b06c7754434"},
-    {file = "torch-2.0.1-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:ef654427d91600129864644e35deea761fb1fe131710180b952a6f2e2207075e"},
-    {file = "torch-2.0.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:25aa43ca80dcdf32f13da04c503ec7afdf8e77e3a0183dd85cd3e53b2842e527"},
-    {file = "torch-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5ef3ea3d25441d3957348f7e99c7824d33798258a2bf5f0f0277cbcadad2e20d"},
-    {file = "torch-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0882243755ff28895e8e6dc6bc26ebcf5aa0911ed81b2a12f241fc4b09075b13"},
-    {file = "torch-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:f66aa6b9580a22b04d0af54fcd042f52406a8479e2b6a550e3d9f95963e168c8"},
-    {file = "torch-2.0.1-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:1adb60d369f2650cac8e9a95b1d5758e25d526a34808f7448d0bd599e4ae9072"},
-    {file = "torch-2.0.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:1bcffc16b89e296826b33b98db5166f990e3b72654a2b90673e817b16c50e32b"},
-    {file = "torch-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:e10e1597f2175365285db1b24019eb6f04d53dcd626c735fc502f1e8b6be9875"},
-    {file = "torch-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:423e0ae257b756bb45a4b49072046772d1ad0c592265c5080070e0767da4e490"},
-    {file = "torch-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8742bdc62946c93f75ff92da00e3803216c6cce9b132fbca69664ca38cfb3e18"},
-    {file = "torch-2.0.1-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:c62df99352bd6ee5a5a8d1832452110435d178b5164de450831a3a8cc14dc680"},
-    {file = "torch-2.0.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:671a2565e3f63b8fe8e42ae3e36ad249fe5e567435ea27b94edaa672a7d0c416"},
-]
-
-[package.dependencies]
-filelock = "*"
-jinja2 = "*"
-networkx = "*"
-sympy = "*"
-typing-extensions = "*"
-
-[package.extras]
-opt-einsum = ["opt-einsum (>=3.3)"]
-
-[[package]]
-name = "torchvision"
-version = "0.15.2"
-description = "image and video datasets and models for torch deep learning"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "torchvision-0.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7754088774e810c5672b142a45dcf20b1bd986a5a7da90f8660c43dc43fb850c"},
-    {file = "torchvision-0.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37eb138e13f6212537a3009ac218695483a635c404b6cc1d8e0d0d978026a86d"},
-    {file = "torchvision-0.15.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:54143f7cc0797d199b98a53b7d21c3f97615762d4dd17ad45a41c7e80d880e73"},
-    {file = "torchvision-0.15.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:1eefebf5fbd01a95fe8f003d623d941601c94b5cec547b420da89cb369d9cf96"},
-    {file = "torchvision-0.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:96fae30c5ca8423f4b9790df0f0d929748e32718d88709b7b567d2f630c042e3"},
-    {file = "torchvision-0.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5f35f6bd5bcc4568e6522e4137fa60fcc72f4fa3e615321c26cd87e855acd398"},
-    {file = "torchvision-0.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:757505a0ab2be7096cb9d2bf4723202c971cceddb72c7952a7e877f773de0f8a"},
-    {file = "torchvision-0.15.2-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:012ad25cfd9019ff9b0714a168727e3845029be1af82296ff1e1482931fa4b80"},
-    {file = "torchvision-0.15.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b02a7ffeaa61448737f39a4210b8ee60234bda0515a0c0d8562f884454105b0f"},
-    {file = "torchvision-0.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:10be76ceded48329d0a0355ac33da131ee3993ff6c125e4a02ab34b5baa2472c"},
-    {file = "torchvision-0.15.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f12415b686dba884fb086f53ac803f692be5a5cdd8a758f50812b30fffea2e4"},
-    {file = "torchvision-0.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:31211c01f8b8ec33b8a638327b5463212e79a03e43c895f88049f97af1bd12fd"},
-    {file = "torchvision-0.15.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c55f9889e436f14b4f84a9c00ebad0d31f5b4626f10cf8018e6c676f92a6d199"},
-    {file = "torchvision-0.15.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9a192f2aa979438f23c20e883980b23d13268ab9f819498774a6d2eb021802c2"},
-    {file = "torchvision-0.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:c07071bc8d02aa8fcdfe139ab6a1ef57d3b64c9e30e84d12d45c9f4d89fb6536"},
-    {file = "torchvision-0.15.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4790260fcf478a41c7ecc60a6d5200a88159fdd8d756e9f29f0f8c59c4a67a68"},
-    {file = "torchvision-0.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:987ab62225b4151a11e53fd06150c5258ced24ac9d7c547e0e4ab6fbca92a5ce"},
-    {file = "torchvision-0.15.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:63df26673e66cba3f17e07c327a8cafa3cce98265dbc3da329f1951d45966838"},
-    {file = "torchvision-0.15.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b85f98d4cc2f72452f6792ab4463a3541bc5678a8cdd3da0e139ba2fe8b56d42"},
-    {file = "torchvision-0.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:07c462524cc1bba5190c16a9d47eac1fca024d60595a310f23c00b4ffff18b30"},
-]
-
-[package.dependencies]
-numpy = "*"
-pillow = ">=5.3.0,<8.3.dev0 || >=8.4.dev0"
-requests = "*"
-torch = "2.0.1"
-
-[package.extras]
-scipy = ["scipy"]
-
-[[package]]
-name = "tqdm"
-version = "4.65.0"
-description = "Fast, Extensible Progress Meter"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"},
-    {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-
-[package.extras]
-dev = ["py-make (>=0.1.0)", "twine", "wheel"]
-notebook = ["ipywidgets (>=6)"]
-slack = ["slack-sdk"]
-telegram = ["requests"]
-
-[[package]]
-name = "transformers"
-version = "4.31.0"
-description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow"
-optional = false
-python-versions = ">=3.8.0"
-files = [
-    {file = "transformers-4.31.0-py3-none-any.whl", hash = "sha256:8487aab0195ce1c2a5ae189305118b9720daddbc7b688edb09ccd79e3b149f6b"},
-    {file = "transformers-4.31.0.tar.gz", hash = "sha256:4302fba920a1c24d3a429a29efff6a63eac03f3f3cf55b55927fc795d01cb273"},
-]
-
-[package.dependencies]
-filelock = "*"
-huggingface-hub = ">=0.14.1,<1.0"
-numpy = ">=1.17"
-packaging = ">=20.0"
-pyyaml = ">=5.1"
-regex = "!=2019.12.17"
-requests = "*"
-safetensors = ">=0.3.1"
-tokenizers = ">=0.11.1,<0.11.3 || >0.11.3,<0.14"
-tqdm = ">=4.27"
-
-[package.extras]
-accelerate = ["accelerate (>=0.20.3)"]
-agents = ["Pillow (<10.0.0)", "accelerate (>=0.20.3)", "datasets (!=2.5.0)", "diffusers", "opencv-python", "sentencepiece (>=0.1.91,!=0.1.92)", "torch (>=1.9,!=1.12.0)"]
-all = ["Pillow (<10.0.0)", "accelerate (>=0.20.3)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.2.8,!=0.3.2,<=0.4.13)", "jaxlib (>=0.1.65,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune]", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx", "timm", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "torch (>=1.9,!=1.12.0)", "torchaudio", "torchvision"]
-audio = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"]
-codecarbon = ["codecarbon (==1.2.0)"]
-deepspeed = ["accelerate (>=0.20.3)", "deepspeed (>=0.9.3)"]
-deepspeed-testing = ["GitPython (<3.1.19)", "accelerate (>=0.20.3)", "beautifulsoup4", "black (>=23.1,<24.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "deepspeed (>=0.9.3)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder (>=0.3.0)", "nltk", "optuna", "parameterized", "protobuf", "psutil", "pytest (>=7.2.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "timeout-decorator"]
-dev = ["GitPython (<3.1.19)", "Pillow (<10.0.0)", "accelerate (>=0.20.3)", "av (==9.2.0)", "beautifulsoup4", "black (>=23.1,<24.0)", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.2.8,!=0.3.2,<=0.4.13)", "jaxlib (>=0.1.65,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pytest (>=7.2.0)", "pytest-timeout", "pytest-xdist", "ray[tune]", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (>=0.0.241,<=0.0.259)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorflow (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx", "timeout-decorator", "timm", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "torch (>=1.9,!=1.12.0)", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"]
-dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (<10.0.0)", "beautifulsoup4", "black (>=23.1,<24.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pytest (>=7.2.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (>=0.0.241,<=0.0.259)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorflow (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "urllib3 (<2.0.0)"]
-dev-torch = ["GitPython (<3.1.19)", "Pillow (<10.0.0)", "accelerate (>=0.20.3)", "beautifulsoup4", "black (>=23.1,<24.0)", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pytest (>=7.2.0)", "pytest-timeout", "pytest-xdist", "ray[tune]", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (>=0.0.241,<=0.0.259)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "timeout-decorator", "timm", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "torch (>=1.9,!=1.12.0)", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"]
-docs = ["Pillow (<10.0.0)", "accelerate (>=0.20.3)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "hf-doc-builder", "jax (>=0.2.8,!=0.3.2,<=0.4.13)", "jaxlib (>=0.1.65,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune]", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx", "timm", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "torch (>=1.9,!=1.12.0)", "torchaudio", "torchvision"]
-docs-specific = ["hf-doc-builder"]
-fairscale = ["fairscale (>0.3)"]
-flax = ["flax (>=0.4.1,<=0.7.0)", "jax (>=0.2.8,!=0.3.2,<=0.4.13)", "jaxlib (>=0.1.65,<=0.4.13)", "optax (>=0.0.8,<=0.1.4)"]
-flax-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"]
-ftfy = ["ftfy"]
-integrations = ["optuna", "ray[tune]", "sigopt"]
-ja = ["fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "rhoknp (>=1.1.0,<1.3.1)", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)"]
-modelcreation = ["cookiecutter (==1.7.3)"]
-natten = ["natten (>=0.14.6)"]
-onnx = ["onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "tf2onnx"]
-onnxruntime = ["onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)"]
-optuna = ["optuna"]
-quality = ["GitPython (<3.1.19)", "black (>=23.1,<24.0)", "datasets (!=2.5.0)", "hf-doc-builder (>=0.3.0)", "isort (>=5.5.4)", "ruff (>=0.0.241,<=0.0.259)", "urllib3 (<2.0.0)"]
-ray = ["ray[tune]"]
-retrieval = ["datasets (!=2.5.0)", "faiss-cpu"]
-sagemaker = ["sagemaker (>=2.31.0)"]
-sentencepiece = ["protobuf", "sentencepiece (>=0.1.91,!=0.1.92)"]
-serving = ["fastapi", "pydantic (<2)", "starlette", "uvicorn"]
-sigopt = ["sigopt"]
-sklearn = ["scikit-learn"]
-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"]
-testing = ["GitPython (<3.1.19)", "beautifulsoup4", "black (>=23.1,<24.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder (>=0.3.0)", "nltk", "parameterized", "protobuf", "psutil", "pytest (>=7.2.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "timeout-decorator"]
-tf = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx"]
-tf-cpu = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow-cpu (>=2.6,<2.14)", "tensorflow-text (<2.14)", "tf2onnx"]
-tf-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"]
-timm = ["timm"]
-tokenizers = ["tokenizers (>=0.11.1,!=0.11.3,<0.14)"]
-torch = ["accelerate (>=0.20.3)", "torch (>=1.9,!=1.12.0)"]
-torch-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"]
-torch-vision = ["Pillow (<10.0.0)", "torchvision"]
-torchhub = ["filelock", "huggingface-hub (>=0.14.1,<1.0)", "importlib-metadata", "numpy (>=1.17)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.11.1,!=0.11.3,<0.14)", "torch (>=1.9,!=1.12.0)", "tqdm (>=4.27)"]
-video = ["av (==9.2.0)", "decord (==0.6.0)"]
-vision = ["Pillow (<10.0.0)"]
-
-[[package]]
-name = "typing-extensions"
-version = "4.7.1"
-description = "Backported and Experimental Type Hints for Python 3.7+"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
-    {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
-]
-
-[[package]]
-name = "typing-inspect"
-version = "0.9.0"
-description = "Runtime inspection utilities for typing module."
-optional = false
-python-versions = "*"
-files = [
-    {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"},
-    {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"},
-]
-
-[package.dependencies]
-mypy-extensions = ">=0.3.0"
-typing-extensions = ">=3.7.4"
-
-[[package]]
-name = "tzdata"
-version = "2023.3"
-description = "Provider of IANA time zone data"
-optional = false
-python-versions = ">=2"
-files = [
-    {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
-    {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
-]
-
-[[package]]
-name = "tzlocal"
-version = "5.0.1"
-description = "tzinfo object for the local timezone"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "tzlocal-5.0.1-py3-none-any.whl", hash = "sha256:f3596e180296aaf2dbd97d124fe76ae3a0e3d32b258447de7b939b3fd4be992f"},
-    {file = "tzlocal-5.0.1.tar.gz", hash = "sha256:46eb99ad4bdb71f3f72b7d24f4267753e240944ecfc16f25d2719ba89827a803"},
-]
-
-[package.dependencies]
-tzdata = {version = "*", markers = "platform_system == \"Windows\""}
-
-[package.extras]
-devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
-
-[[package]]
-name = "unstructured"
-version = "0.8.0"
-description = "A library that prepares raw documents for downstream ML tasks."
-optional = false
-python-versions = ">=3.7.0"
-files = [
-    {file = "unstructured-0.8.0-py3-none-any.whl", hash = "sha256:d6f574327f6b371f8bbe8d2c6861d8b40114ead9b920054c3601449ec72c3e42"},
-    {file = "unstructured-0.8.0.tar.gz", hash = "sha256:528b9140ef56bee3f7eabd23e7203f3f6890c1a72188d640985f86a3f842c565"},
-]
-
-[package.dependencies]
-argilla = "*"
-chardet = "*"
-filetype = "*"
-lxml = "*"
-markdown = "*"
-msg-parser = "*"
-nltk = "*"
-openpyxl = "*"
-pandas = "*"
-pdf2image = "*"
-"pdfminer.six" = "*"
-pillow = "*"
-pypandoc = "*"
-python-docx = "*"
-python-magic = "*"
-python-pptx = "*"
-requests = "*"
-tabulate = "*"
-xlrd = "*"
-
-[package.extras]
-azure = ["adlfs", "fsspec"]
-discord = ["discord-py"]
-dropbox = ["dropboxdrivefs", "fsspec"]
-elasticsearch = ["elasticsearch", "jq"]
-gcs = ["fsspec", "gcsfs"]
-github = ["pygithub (==1.58.2)"]
-gitlab = ["python-gitlab"]
-google-drive = ["google-api-python-client"]
-huggingface = ["langdetect", "sacremoses", "sentencepiece", "torch", "transformers"]
-local-inference = ["unstructured-inference (==0.5.5)"]
-reddit = ["praw"]
-s3 = ["fsspec", "s3fs"]
-slack = ["slack-sdk"]
-wikipedia = ["wikipedia"]
-
-[[package]]
-name = "urllib3"
-version = "2.0.3"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"},
-    {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"},
-]
-
-[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
-
-[[package]]
-name = "uvicorn"
-version = "0.22.0"
-description = "The lightning-fast ASGI server."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "uvicorn-0.22.0-py3-none-any.whl", hash = "sha256:e9434d3bbf05f310e762147f769c9f21235ee118ba2d2bf1155a7196448bd996"},
-    {file = "uvicorn-0.22.0.tar.gz", hash = "sha256:79277ae03db57ce7d9aa0567830bbb51d7a612f54d6e1e3e92da3ef24c2c8ed8"},
-]
-
-[package.dependencies]
-click = ">=7.0"
-colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
-h11 = ">=0.8"
-httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
-python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
-pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
-uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
-watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
-websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
-
-[package.extras]
-standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
-
-[[package]]
-name = "uvloop"
-version = "0.17.0"
-description = "Fast implementation of asyncio event loop on top of libuv"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"},
-    {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c"},
-    {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d"},
-    {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024"},
-    {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa"},
-    {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811"},
-    {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c"},
-    {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e"},
-    {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539"},
-    {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4"},
-    {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05"},
-    {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376"},
-    {file = "uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b"},
-    {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8"},
-    {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62"},
-    {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d"},
-    {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667"},
-    {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738"},
-    {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20"},
-    {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f"},
-    {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595"},
-    {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578"},
-    {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474"},
-    {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b"},
-    {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c"},
-    {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8"},
-    {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c"},
-    {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9"},
-    {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded"},
-    {file = "uvloop-0.17.0.tar.gz", hash = "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1"},
-]
-
-[package.extras]
-dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
-docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
-test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"]
-
-[[package]]
-name = "watchfiles"
-version = "0.19.0"
-description = "Simple, modern and high performance file watching and code reload in python."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "watchfiles-0.19.0-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:91633e64712df3051ca454ca7d1b976baf842d7a3640b87622b323c55f3345e7"},
-    {file = "watchfiles-0.19.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:b6577b8c6c8701ba8642ea9335a129836347894b666dd1ec2226830e263909d3"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:18b28f6ad871b82df9542ff958d0c86bb0d8310bb09eb8e87d97318a3b5273af"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fac19dc9cbc34052394dbe81e149411a62e71999c0a19e1e09ce537867f95ae0"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ea3397aecbc81c19ed7f025e051a7387feefdb789cf768ff994c1228182fda"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0376deac92377817e4fb8f347bf559b7d44ff556d9bc6f6208dd3f79f104aaf"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c75eff897786ee262c9f17a48886f4e98e6cfd335e011c591c305e5d083c056"},
-    {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb5d45c4143c1dd60f98a16187fd123eda7248f84ef22244818c18d531a249d1"},
-    {file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:79c533ff593db861ae23436541f481ec896ee3da4e5db8962429b441bbaae16e"},
-    {file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3d7d267d27aceeeaa3de0dd161a0d64f0a282264d592e335fff7958cc0cbae7c"},
-    {file = "watchfiles-0.19.0-cp37-abi3-win32.whl", hash = "sha256:176a9a7641ec2c97b24455135d58012a5be5c6217fc4d5fef0b2b9f75dbf5154"},
-    {file = "watchfiles-0.19.0-cp37-abi3-win_amd64.whl", hash = "sha256:945be0baa3e2440151eb3718fd8846751e8b51d8de7b884c90b17d271d34cae8"},
-    {file = "watchfiles-0.19.0-cp37-abi3-win_arm64.whl", hash = "sha256:0089c6dc24d436b373c3c57657bf4f9a453b13767150d17284fc6162b2791911"},
-    {file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cae3dde0b4b2078f31527acff6f486e23abed307ba4d3932466ba7cdd5ecec79"},
-    {file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f3920b1285a7d3ce898e303d84791b7bf40d57b7695ad549dc04e6a44c9f120"},
-    {file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9afd0d69429172c796164fd7fe8e821ade9be983f51c659a38da3faaaaac44dc"},
-    {file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68dce92b29575dda0f8d30c11742a8e2b9b8ec768ae414b54f7453f27bdf9545"},
-    {file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5569fc7f967429d4bc87e355cdfdcee6aabe4b620801e2cf5805ea245c06097c"},
-    {file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5471582658ea56fca122c0f0d0116a36807c63fefd6fdc92c71ca9a4491b6b48"},
-    {file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b538014a87f94d92f98f34d3e6d2635478e6be6423a9ea53e4dd96210065e193"},
-    {file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20b44221764955b1e703f012c74015306fb7e79a00c15370785f309b1ed9aa8d"},
-    {file = "watchfiles-0.19.0.tar.gz", hash = "sha256:d9b073073e048081e502b6c6b0b88714c026a1a4c890569238d04aca5f9ca74b"},
-]
-
-[package.dependencies]
-anyio = ">=3.0.0"
-
-[[package]]
-name = "websockets"
-version = "11.0.3"
-description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"},
-    {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"},
-    {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"},
-    {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"},
-    {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"},
-    {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"},
-    {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"},
-    {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"},
-    {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"},
-    {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"},
-    {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"},
-    {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"},
-    {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"},
-    {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"},
-    {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"},
-    {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"},
-    {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"},
-    {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"},
-    {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"},
-    {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"},
-    {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"},
-    {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"},
-    {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"},
-    {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"},
-    {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"},
-    {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"},
-    {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"},
-    {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"},
-    {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"},
-    {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"},
-    {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"},
-    {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"},
-    {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"},
-    {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"},
-    {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"},
-    {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"},
-    {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"},
-    {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"},
-    {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"},
-    {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"},
-    {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"},
-    {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"},
-    {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"},
-    {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"},
-    {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"},
-    {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"},
-    {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"},
-    {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"},
-    {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"},
-    {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"},
-    {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"},
-    {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"},
-    {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"},
-    {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"},
-    {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"},
-    {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"},
-    {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"},
-    {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"},
-    {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"},
-    {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"},
-    {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"},
-    {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"},
-    {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"},
-    {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"},
-    {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"},
-    {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"},
-    {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"},
-    {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"},
-    {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"},
-    {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"},
-]
-
-[[package]]
-name = "win-unicode-console"
-version = "0.5"
-description = "Enable Unicode input and display when running Python from Windows console."
-optional = false
-python-versions = "*"
-files = [
-    {file = "win_unicode_console-0.5.zip", hash = "sha256:d4142d4d56d46f449d6f00536a73625a871cba040f0bc1a2e305a04578f07d1e"},
-]
-
-[[package]]
-name = "xlrd"
-version = "2.0.1"
-description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
-files = [
-    {file = "xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd"},
-    {file = "xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88"},
-]
-
-[package.extras]
-build = ["twine", "wheel"]
-docs = ["sphinx"]
-test = ["pytest", "pytest-cov"]
-
-[[package]]
-name = "xlsxwriter"
-version = "3.1.2"
-description = "A Python module for creating Excel XLSX files."
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "XlsxWriter-3.1.2-py3-none-any.whl", hash = "sha256:331508ff39d610ecdaf979e458840bc1eab6e6a02cfd5d08f044f0f73636236f"},
-    {file = "XlsxWriter-3.1.2.tar.gz", hash = "sha256:78751099a770273f1c98b8d6643351f68f98ae8e6acf9d09d37dc6798f8cd3de"},
-]
-
-[[package]]
-name = "yarl"
-version = "1.9.2"
-description = "Yet another URL library"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"},
-    {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"},
-    {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"},
-    {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"},
-    {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"},
-    {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"},
-    {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"},
-    {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"},
-    {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"},
-    {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"},
-    {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"},
-    {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"},
-    {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"},
-    {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"},
-    {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"},
-    {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
-    {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
-    {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
-    {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
-    {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
-    {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
-    {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
-    {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
-    {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
-    {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
-    {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
-    {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
-    {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
-    {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
-    {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
-    {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"},
-    {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"},
-    {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"},
-    {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"},
-    {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"},
-    {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"},
-    {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"},
-    {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"},
-    {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"},
-    {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"},
-    {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"},
-    {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"},
-    {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"},
-    {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"},
-    {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"},
-    {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"},
-    {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"},
-    {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"},
-    {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"},
-    {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"},
-    {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"},
-    {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"},
-    {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"},
-    {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"},
-    {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"},
-    {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"},
-    {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"},
-    {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"},
-    {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"},
-    {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"},
-    {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"},
-    {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"},
-    {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"},
-    {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"},
-    {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"},
-    {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"},
-    {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"},
-    {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"},
-    {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"},
-    {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"},
-    {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"},
-    {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"},
-    {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"},
-    {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
-]
-
-[package.dependencies]
-idna = ">=2.0"
-multidict = ">=4.0"
-
-[[package]]
-name = "zipp"
-version = "3.16.0"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "zipp-3.16.0-py3-none-any.whl", hash = "sha256:5dadc3ad0a1f825fe42ce1bce0f2fc5a13af2e6b2d386af5b0ff295bc0a287d3"},
-    {file = "zipp-3.16.0.tar.gz", hash = "sha256:1876cb065531855bbe83b6c489dcf69ecc28f1068d8e95959fe8bbc77774c941"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
-
-[[package]]
-name = "zstandard"
-version = "0.21.0"
-description = "Zstandard bindings for Python"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "zstandard-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:649a67643257e3b2cff1c0a73130609679a5673bf389564bc6d4b164d822a7ce"},
-    {file = "zstandard-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:144a4fe4be2e747bf9c646deab212666e39048faa4372abb6a250dab0f347a29"},
-    {file = "zstandard-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b72060402524ab91e075881f6b6b3f37ab715663313030d0ce983da44960a86f"},
-    {file = "zstandard-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8257752b97134477fb4e413529edaa04fc0457361d304c1319573de00ba796b1"},
-    {file = "zstandard-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c053b7c4cbf71cc26808ed67ae955836232f7638444d709bfc302d3e499364fa"},
-    {file = "zstandard-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2769730c13638e08b7a983b32cb67775650024632cd0476bf1ba0e6360f5ac7d"},
-    {file = "zstandard-0.21.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7d3bc4de588b987f3934ca79140e226785d7b5e47e31756761e48644a45a6766"},
-    {file = "zstandard-0.21.0-cp310-cp310-win32.whl", hash = "sha256:67829fdb82e7393ca68e543894cd0581a79243cc4ec74a836c305c70a5943f07"},
-    {file = "zstandard-0.21.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6048a287f8d2d6e8bc67f6b42a766c61923641dd4022b7fd3f7439e17ba5a4d"},
-    {file = "zstandard-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7f2afab2c727b6a3d466faee6974a7dad0d9991241c498e7317e5ccf53dbc766"},
-    {file = "zstandard-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff0852da2abe86326b20abae912d0367878dd0854b8931897d44cfeb18985472"},
-    {file = "zstandard-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d12fa383e315b62630bd407477d750ec96a0f438447d0e6e496ab67b8b451d39"},
-    {file = "zstandard-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1b9703fe2e6b6811886c44052647df7c37478af1b4a1a9078585806f42e5b15"},
-    {file = "zstandard-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df28aa5c241f59a7ab524f8ad8bb75d9a23f7ed9d501b0fed6d40ec3064784e8"},
-    {file = "zstandard-0.21.0-cp311-cp311-win32.whl", hash = "sha256:0aad6090ac164a9d237d096c8af241b8dcd015524ac6dbec1330092dba151657"},
-    {file = "zstandard-0.21.0-cp311-cp311-win_amd64.whl", hash = "sha256:48b6233b5c4cacb7afb0ee6b4f91820afbb6c0e3ae0fa10abbc20000acdf4f11"},
-    {file = "zstandard-0.21.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e7d560ce14fd209db6adacce8908244503a009c6c39eee0c10f138996cd66d3e"},
-    {file = "zstandard-0.21.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e6e131a4df2eb6f64961cea6f979cdff22d6e0d5516feb0d09492c8fd36f3bc"},
-    {file = "zstandard-0.21.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1e0c62a67ff425927898cf43da2cf6b852289ebcc2054514ea9bf121bec10a5"},
-    {file = "zstandard-0.21.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1545fb9cb93e043351d0cb2ee73fa0ab32e61298968667bb924aac166278c3fc"},
-    {file = "zstandard-0.21.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe6c821eb6870f81d73bf10e5deed80edcac1e63fbc40610e61f340723fd5f7c"},
-    {file = "zstandard-0.21.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ddb086ea3b915e50f6604be93f4f64f168d3fc3cef3585bb9a375d5834392d4f"},
-    {file = "zstandard-0.21.0-cp37-cp37m-win32.whl", hash = "sha256:57ac078ad7333c9db7a74804684099c4c77f98971c151cee18d17a12649bc25c"},
-    {file = "zstandard-0.21.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1243b01fb7926a5a0417120c57d4c28b25a0200284af0525fddba812d575f605"},
-    {file = "zstandard-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea68b1ba4f9678ac3d3e370d96442a6332d431e5050223626bdce748692226ea"},
-    {file = "zstandard-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8070c1cdb4587a8aa038638acda3bd97c43c59e1e31705f2766d5576b329e97c"},
-    {file = "zstandard-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af612c96599b17e4930fe58bffd6514e6c25509d120f4eae6031b7595912f85"},
-    {file = "zstandard-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff891e37b167bc477f35562cda1248acc115dbafbea4f3af54ec70821090965"},
-    {file = "zstandard-0.21.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9fec02ce2b38e8b2e86079ff0b912445495e8ab0b137f9c0505f88ad0d61296"},
-    {file = "zstandard-0.21.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdbe350691dec3078b187b8304e6a9c4d9db3eb2d50ab5b1d748533e746d099"},
-    {file = "zstandard-0.21.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b69cccd06a4a0a1d9fb3ec9a97600055cf03030ed7048d4bcb88c574f7895773"},
-    {file = "zstandard-0.21.0-cp38-cp38-win32.whl", hash = "sha256:9980489f066a391c5572bc7dc471e903fb134e0b0001ea9b1d3eff85af0a6f1b"},
-    {file = "zstandard-0.21.0-cp38-cp38-win_amd64.whl", hash = "sha256:0e1e94a9d9e35dc04bf90055e914077c80b1e0c15454cc5419e82529d3e70728"},
-    {file = "zstandard-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2d61675b2a73edcef5e327e38eb62bdfc89009960f0e3991eae5cc3d54718de"},
-    {file = "zstandard-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25fbfef672ad798afab12e8fd204d122fca3bc8e2dcb0a2ba73bf0a0ac0f5f07"},
-    {file = "zstandard-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62957069a7c2626ae80023998757e27bd28d933b165c487ab6f83ad3337f773d"},
-    {file = "zstandard-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e10ed461e4807471075d4b7a2af51f5234c8f1e2a0c1d37d5ca49aaaad49e8"},
-    {file = "zstandard-0.21.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9cff89a036c639a6a9299bf19e16bfb9ac7def9a7634c52c257166db09d950e7"},
-    {file = "zstandard-0.21.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52b2b5e3e7670bd25835e0e0730a236f2b0df87672d99d3bf4bf87248aa659fb"},
-    {file = "zstandard-0.21.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1367da0dde8ae5040ef0413fb57b5baeac39d8931c70536d5f013b11d3fc3a5"},
-    {file = "zstandard-0.21.0-cp39-cp39-win32.whl", hash = "sha256:db62cbe7a965e68ad2217a056107cc43d41764c66c895be05cf9c8b19578ce9c"},
-    {file = "zstandard-0.21.0-cp39-cp39-win_amd64.whl", hash = "sha256:a8d200617d5c876221304b0e3fe43307adde291b4a897e7b0617a61611dfff6a"},
-    {file = "zstandard-0.21.0.tar.gz", hash = "sha256:f08e3a10d01a247877e4cb61a82a319ea746c356a3786558bed2481e6c405546"},
-]
-
-[package.dependencies]
-cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""}
-
-[package.extras]
-cffi = ["cffi (>=1.11)"]
-
-[metadata]
-lock-version = "2.0"
-python-versions = "^3.10"
-content-hash = "92c090ae111eaa2821badd95cf3880b678fcbf647241c9edc8f789009acf76c8"
diff --git a/ollama/examples/langchain-python-rag-privategpt/privateGPT.py b/ollama/examples/langchain-python-rag-privategpt/privateGPT.py
deleted file mode 100755
index 7d97a56..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/privateGPT.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-from langchain.chains import RetrievalQA
-from langchain.embeddings import HuggingFaceEmbeddings
-from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
-from langchain.vectorstores import Chroma
-from langchain.llms import Ollama
-import chromadb
-import os
-import argparse
-import time
-
-model = os.environ.get("MODEL", "llama2-uncensored")
-# For embeddings model, the example uses a sentence-transformers model
-# https://www.sbert.net/docs/pretrained_models.html 
-# "The all-mpnet-base-v2 model provides the best quality, while all-MiniLM-L6-v2 is 5 times faster and still offers good quality."
-embeddings_model_name = os.environ.get("EMBEDDINGS_MODEL_NAME", "all-MiniLM-L6-v2")
-persist_directory = os.environ.get("PERSIST_DIRECTORY", "db")
-target_source_chunks = int(os.environ.get('TARGET_SOURCE_CHUNKS',4))
-
-from constants import CHROMA_SETTINGS
-
-def main():
-    # Parse the command line arguments
-    args = parse_arguments()
-    embeddings = HuggingFaceEmbeddings(model_name=embeddings_model_name)
-
-    db = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
-
-    retriever = db.as_retriever(search_kwargs={"k": target_source_chunks})
-    # activate/deactivate the streaming StdOut callback for LLMs
-    callbacks = [] if args.mute_stream else [StreamingStdOutCallbackHandler()]
-
-    llm = Ollama(model=model, callbacks=callbacks)
-
-    qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever, return_source_documents= not args.hide_source)
-    # Interactive questions and answers
-    while True:
-        query = input("\nEnter a query: ")
-        if query == "exit":
-            break
-        if query.strip() == "":
-            continue
-
-        # Get the answer from the chain
-        start = time.time()
-        res = qa(query)
-        answer, docs = res['result'], [] if args.hide_source else res['source_documents']
-        end = time.time()
-
-        # Print the result
-        print("\n\n> Question:")
-        print(query)
-        print(answer)
-
-        # Print the relevant sources used for the answer
-        for document in docs:
-            print("\n> " + document.metadata["source"] + ":")
-            print(document.page_content)
-
-def parse_arguments():
-    parser = argparse.ArgumentParser(description='privateGPT: Ask questions to your documents without an internet connection, '
-                                                 'using the power of LLMs.')
-    parser.add_argument("--hide-source", "-S", action='store_true',
-                        help='Use this flag to disable printing of source documents used for answers.')
-
-    parser.add_argument("--mute-stream", "-M",
-                        action='store_true',
-                        help='Use this flag to disable the streaming StdOut callback for LLMs.')
-
-    return parser.parse_args()
-
-
-if __name__ == "__main__":
-    main()
diff --git a/ollama/examples/langchain-python-rag-privategpt/pyproject.toml b/ollama/examples/langchain-python-rag-privategpt/pyproject.toml
deleted file mode 100755
index fa65a73..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/pyproject.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-[tool.poetry]
-name = "privategpt"
-version = "0.1.0"
-description = ""
-authors = ["Ivan Martinez "]
-license = "Apache Version 2.0"
-readme = "README.md"
-
-[tool.poetry.dependencies]
-python = "^3.10"
-langchain = "0.0.261"
-gpt4all = "^1.0.3"
-chromadb = "^0.3.26"
-PyMuPDF = "^1.22.5"
-python-dotenv = "^1.0.0"
-unstructured = "^0.8.0"
-extract-msg = "^0.41.5"
-tabulate = "^0.9.0"
-pandoc = "^2.3"
-pypandoc = "^1.11"
-tqdm = "^4.65.0"
-sentence-transformers = "^2.2.2"
-
-[build-system]
-requires = ["poetry-core"]
-build-backend = "poetry.core.masonry.api"
diff --git a/ollama/examples/langchain-python-rag-privategpt/requirements.txt b/ollama/examples/langchain-python-rag-privategpt/requirements.txt
deleted file mode 100755
index 0aad1fe..0000000
--- a/ollama/examples/langchain-python-rag-privategpt/requirements.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-langchain==0.0.274
-gpt4all==1.0.8
-chromadb==0.4.7
-llama-cpp-python==0.1.81
-urllib3==2.0.4
-PyMuPDF==1.23.5
-python-dotenv==1.0.0
-unstructured==0.10.8
-extract-msg==0.45.0
-tabulate==0.9.0
-pandoc==2.3
-pypandoc==1.11
-tqdm==4.66.1
-sentence_transformers==2.2.2
-numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability
\ No newline at end of file
diff --git a/ollama/examples/langchain-python-rag-websummary/README.md b/ollama/examples/langchain-python-rag-websummary/README.md
deleted file mode 100755
index 29c706a..0000000
--- a/ollama/examples/langchain-python-rag-websummary/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# LangChain Web Summarization
-
-This example summarizes the website, [https://ollama.com/blog/run-llama2-uncensored-locally](https://ollama.com/blog/run-llama2-uncensored-locally)
-
-## Running the Example
-
-1. Ensure you have the `llama3.1` model installed:
-
-   ```bash
-   ollama pull llama3.1
-   ```
-
-2. Install the Python Requirements.
-
-   ```bash
-   pip install -r requirements.txt
-   ```
-
-3. Run the example:
-
-   ```bash
-   python main.py
-   ```
diff --git a/ollama/examples/langchain-python-rag-websummary/main.py b/ollama/examples/langchain-python-rag-websummary/main.py
deleted file mode 100755
index 77b09fb..0000000
--- a/ollama/examples/langchain-python-rag-websummary/main.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from langchain_community.llms import Ollama
-from langchain_community.document_loaders import WebBaseLoader
-from langchain.chains.summarize import load_summarize_chain
-
-loader = WebBaseLoader("https://ollama.com/blog/run-llama2-uncensored-locally")
-docs = loader.load()
-
-llm = Ollama(model="llama3.1")
-chain = load_summarize_chain(llm, chain_type="stuff")
-
-result = chain.invoke(docs)
-print(result)
diff --git a/ollama/examples/langchain-python-rag-websummary/requirements.txt b/ollama/examples/langchain-python-rag-websummary/requirements.txt
deleted file mode 100755
index 33cf51b..0000000
--- a/ollama/examples/langchain-python-rag-websummary/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-langchain==0.0.259
diff --git a/ollama/examples/langchain-python-simple/README.md b/ollama/examples/langchain-python-simple/README.md
deleted file mode 100755
index 60db2c8..0000000
--- a/ollama/examples/langchain-python-simple/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# LangChain
-
-This example is a basic "hello world" of using LangChain with Ollama.
-
-## Running the Example
-
-1. Ensure you have the `llama3.1` model installed:
-
-   ```bash
-   ollama pull llama3.1
-   ```
-
-2. Install the Python Requirements.
-
-   ```bash
-   pip install -r requirements.txt
-   ```
-
-3. Run the example:
-
-   ```bash
-   python main.py
-   ```
diff --git a/ollama/examples/langchain-python-simple/main.py b/ollama/examples/langchain-python-simple/main.py
deleted file mode 100755
index a7ed81d..0000000
--- a/ollama/examples/langchain-python-simple/main.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from langchain.llms import Ollama
-
-input = input("What is your question?")
-llm = Ollama(model="llama3.1")
-res = llm.predict(input)
-print (res)
diff --git a/ollama/examples/langchain-python-simple/requirements.txt b/ollama/examples/langchain-python-simple/requirements.txt
deleted file mode 100755
index 33cf51b..0000000
--- a/ollama/examples/langchain-python-simple/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-langchain==0.0.259
diff --git a/ollama/examples/langchain-typescript-simple/README.md b/ollama/examples/langchain-typescript-simple/README.md
deleted file mode 100755
index 7c65ccf..0000000
--- a/ollama/examples/langchain-typescript-simple/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# LangChain
-
-This example is a basic "hello world" of using LangChain with Ollama using Node.js and Typescript.
-
-## Running the Example
-
-1. Install the prerequisites:
-
-   ```bash
-   npm install
-   ```
-
-2. Ensure the `mistral` model is available:
-
-   ```bash
-   ollama pull mistral
-   ```
-
-3. Run the example:
-
-   ```bash
-   npm start
-   ```
diff --git a/ollama/examples/langchain-typescript-simple/main.ts b/ollama/examples/langchain-typescript-simple/main.ts
deleted file mode 100755
index 53a5837..0000000
--- a/ollama/examples/langchain-typescript-simple/main.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Ollama } from 'langchain/llms/ollama';
-import * as readline from "readline";
-
-async function main() {
-  const ollama = new Ollama({
-    model: 'mistral'    
-    // other parameters can be found at https://js.langchain.com/docs/api/llms_ollama/classes/Ollama
-  });
-
-  const rl = readline.createInterface({
-    input: process.stdin,
-    output: process.stdout,
-  });
-
-  rl.question("What is your question: \n", async (user_input) => {
-    const stream = await ollama.stream(user_input);
-  
-    for await (const chunk of stream) {
-      process.stdout.write(chunk);
-    }
-    rl.close();
-  })
-}
-
-main();
\ No newline at end of file
diff --git a/ollama/examples/langchain-typescript-simple/package-lock.json b/ollama/examples/langchain-typescript-simple/package-lock.json
deleted file mode 100755
index 90587d2..0000000
--- a/ollama/examples/langchain-typescript-simple/package-lock.json
+++ /dev/null
@@ -1,997 +0,0 @@
-{
-  "name": "langchain-typescript-simple",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "dependencies": {
-        "langchain": "^0.0.165"
-      },
-      "devDependencies": {
-        "typescript": "^5.2.2"
-      }
-    },
-    "node_modules/@anthropic-ai/sdk": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.6.2.tgz",
-      "integrity": "sha512-fB9PUj9RFT+XjkL+E9Ol864ZIJi+1P8WnbHspN3N3/GK2uSzjd0cbVIKTGgf4v3N8MwaQu+UWnU7C4BG/fap/g==",
-      "dependencies": {
-        "@types/node": "^18.11.18",
-        "@types/node-fetch": "^2.6.4",
-        "abort-controller": "^3.0.0",
-        "agentkeepalive": "^4.2.1",
-        "digest-fetch": "^1.3.0",
-        "form-data-encoder": "1.7.2",
-        "formdata-node": "^4.3.2",
-        "node-fetch": "^2.6.7"
-      }
-    },
-    "node_modules/@types/node": {
-      "version": "18.18.4",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.4.tgz",
-      "integrity": "sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ=="
-    },
-    "node_modules/@types/node-fetch": {
-      "version": "2.6.6",
-      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz",
-      "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==",
-      "dependencies": {
-        "@types/node": "*",
-        "form-data": "^4.0.0"
-      }
-    },
-    "node_modules/@types/retry": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
-      "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="
-    },
-    "node_modules/@types/uuid": {
-      "version": "9.0.5",
-      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz",
-      "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ=="
-    },
-    "node_modules/abort-controller": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
-      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
-      "dependencies": {
-        "event-target-shim": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=6.5"
-      }
-    },
-    "node_modules/agentkeepalive": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
-      "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
-      "dependencies": {
-        "humanize-ms": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 8.0.0"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
-    "node_modules/asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
-    },
-    "node_modules/base-64": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
-      "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
-    },
-    "node_modules/base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/binary-search": {
-      "version": "1.3.6",
-      "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
-      "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
-    },
-    "node_modules/camelcase": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
-      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/charenc": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
-      "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/combined-stream": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-      "dependencies": {
-        "delayed-stream": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/commander": {
-      "version": "10.0.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
-      "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/crypt": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
-      "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/digest-fetch": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz",
-      "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==",
-      "dependencies": {
-        "base-64": "^0.1.0",
-        "md5": "^2.3.0"
-      }
-    },
-    "node_modules/event-target-shim": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
-      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/eventemitter3": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
-    },
-    "node_modules/expr-eval": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/expr-eval/-/expr-eval-2.0.2.tgz",
-      "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg=="
-    },
-    "node_modules/flat": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
-      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
-      "bin": {
-        "flat": "cli.js"
-      }
-    },
-    "node_modules/form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/form-data-encoder": {
-      "version": "1.7.2",
-      "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
-      "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
-    },
-    "node_modules/formdata-node": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
-      "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
-      "dependencies": {
-        "node-domexception": "1.0.0",
-        "web-streams-polyfill": "4.0.0-beta.3"
-      },
-      "engines": {
-        "node": ">= 12.20"
-      }
-    },
-    "node_modules/humanize-ms": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
-      "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
-      "dependencies": {
-        "ms": "^2.0.0"
-      }
-    },
-    "node_modules/is-any-array": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-any-array/-/is-any-array-2.0.1.tgz",
-      "integrity": "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ=="
-    },
-    "node_modules/is-buffer": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-    },
-    "node_modules/js-tiktoken": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.7.tgz",
-      "integrity": "sha512-biba8u/clw7iesNEWLOLwrNGoBP2lA+hTaBLs/D45pJdUPFXyxD6nhcDVtADChghv4GgyAiMKYMiRx7x6h7Biw==",
-      "dependencies": {
-        "base64-js": "^1.5.1"
-      }
-    },
-    "node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/jsonpointer": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
-      "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/langchain": {
-      "version": "0.0.165",
-      "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.0.165.tgz",
-      "integrity": "sha512-CpbNpjwaE+9lzjdw+pZz0VgnRrFivEgr7CVp9dDaAb5JpaJAA4V2v6uQ9ZPN+TSqupTQ79HFn2sfyZVEl2EG7Q==",
-      "dependencies": {
-        "@anthropic-ai/sdk": "^0.6.2",
-        "ansi-styles": "^5.0.0",
-        "binary-extensions": "^2.2.0",
-        "camelcase": "6",
-        "decamelize": "^1.2.0",
-        "expr-eval": "^2.0.2",
-        "flat": "^5.0.2",
-        "js-tiktoken": "^1.0.7",
-        "js-yaml": "^4.1.0",
-        "jsonpointer": "^5.0.1",
-        "langchainhub": "~0.0.6",
-        "langsmith": "~0.0.31",
-        "ml-distance": "^4.0.0",
-        "object-hash": "^3.0.0",
-        "openai": "~4.4.0",
-        "openapi-types": "^12.1.3",
-        "p-queue": "^6.6.2",
-        "p-retry": "4",
-        "uuid": "^9.0.0",
-        "yaml": "^2.2.1",
-        "zod": "^3.22.3",
-        "zod-to-json-schema": "^3.20.4"
-      },
-      "engines": {
-        "node": ">=18"
-      },
-      "peerDependencies": {
-        "@aws-crypto/sha256-js": "^5.0.0",
-        "@aws-sdk/client-bedrock-runtime": "^3.422.0",
-        "@aws-sdk/client-dynamodb": "^3.310.0",
-        "@aws-sdk/client-kendra": "^3.352.0",
-        "@aws-sdk/client-lambda": "^3.310.0",
-        "@aws-sdk/client-s3": "^3.310.0",
-        "@aws-sdk/client-sagemaker-runtime": "^3.310.0",
-        "@aws-sdk/client-sfn": "^3.310.0",
-        "@aws-sdk/credential-provider-node": "^3.388.0",
-        "@azure/storage-blob": "^12.15.0",
-        "@clickhouse/client": "^0.0.14",
-        "@cloudflare/ai": "^1.0.12",
-        "@elastic/elasticsearch": "^8.4.0",
-        "@getmetal/metal-sdk": "*",
-        "@getzep/zep-js": "^0.7.0",
-        "@gomomento/sdk": "^1.23.0",
-        "@google-ai/generativelanguage": "^0.2.1",
-        "@google-cloud/storage": "^6.10.1",
-        "@huggingface/inference": "^1.5.1",
-        "@mozilla/readability": "*",
-        "@notionhq/client": "^2.2.10",
-        "@opensearch-project/opensearch": "*",
-        "@pinecone-database/pinecone": "^1.1.0",
-        "@planetscale/database": "^1.8.0",
-        "@qdrant/js-client-rest": "^1.2.0",
-        "@raycast/api": "^1.55.2",
-        "@smithy/eventstream-codec": "^2.0.5",
-        "@smithy/protocol-http": "^3.0.6",
-        "@smithy/signature-v4": "^2.0.10",
-        "@smithy/util-utf8": "^2.0.0",
-        "@supabase/postgrest-js": "^1.1.1",
-        "@supabase/supabase-js": "^2.10.0",
-        "@tensorflow-models/universal-sentence-encoder": "*",
-        "@tensorflow/tfjs-converter": "*",
-        "@tensorflow/tfjs-core": "*",
-        "@upstash/redis": "^1.20.6",
-        "@vercel/postgres": "^0.5.0",
-        "@writerai/writer-sdk": "^0.40.2",
-        "@xata.io/client": "^0.25.1",
-        "@xenova/transformers": "^2.5.4",
-        "@zilliz/milvus2-sdk-node": ">=2.2.7",
-        "apify-client": "^2.7.1",
-        "axios": "*",
-        "cassandra-driver": "^4.6.4",
-        "cheerio": "^1.0.0-rc.12",
-        "chromadb": "*",
-        "cohere-ai": ">=6.0.0",
-        "d3-dsv": "^2.0.0",
-        "epub2": "^3.0.1",
-        "faiss-node": "^0.3.0",
-        "fast-xml-parser": "^4.2.7",
-        "firebase-admin": "^11.9.0",
-        "google-auth-library": "^8.9.0",
-        "googleapis": "^126.0.1",
-        "hnswlib-node": "^1.4.2",
-        "html-to-text": "^9.0.5",
-        "ignore": "^5.2.0",
-        "ioredis": "^5.3.2",
-        "jsdom": "*",
-        "llmonitor": "*",
-        "lodash": "^4.17.21",
-        "mammoth": "*",
-        "mongodb": "^5.2.0",
-        "mysql2": "^3.3.3",
-        "neo4j-driver": "*",
-        "node-llama-cpp": "*",
-        "notion-to-md": "^3.1.0",
-        "pdf-parse": "1.1.1",
-        "peggy": "^3.0.2",
-        "pg": "^8.11.0",
-        "pg-copy-streams": "^6.0.5",
-        "pickleparser": "^0.1.0",
-        "playwright": "^1.32.1",
-        "portkey-ai": "^0.1.11",
-        "puppeteer": "^19.7.2",
-        "redis": "^4.6.4",
-        "replicate": "^0.18.0",
-        "sonix-speech-recognition": "^2.1.1",
-        "srt-parser-2": "^1.2.2",
-        "typeorm": "^0.3.12",
-        "typesense": "^1.5.3",
-        "usearch": "^1.1.1",
-        "vectordb": "^0.1.4",
-        "voy-search": "0.6.2",
-        "weaviate-ts-client": "^1.4.0",
-        "web-auth-library": "^1.0.3",
-        "youtube-transcript": "^1.0.6",
-        "youtubei.js": "^5.8.0"
-      },
-      "peerDependenciesMeta": {
-        "@aws-crypto/sha256-js": {
-          "optional": true
-        },
-        "@aws-sdk/client-bedrock-runtime": {
-          "optional": true
-        },
-        "@aws-sdk/client-dynamodb": {
-          "optional": true
-        },
-        "@aws-sdk/client-kendra": {
-          "optional": true
-        },
-        "@aws-sdk/client-lambda": {
-          "optional": true
-        },
-        "@aws-sdk/client-s3": {
-          "optional": true
-        },
-        "@aws-sdk/client-sagemaker-runtime": {
-          "optional": true
-        },
-        "@aws-sdk/client-sfn": {
-          "optional": true
-        },
-        "@aws-sdk/credential-provider-node": {
-          "optional": true
-        },
-        "@azure/storage-blob": {
-          "optional": true
-        },
-        "@clickhouse/client": {
-          "optional": true
-        },
-        "@cloudflare/ai": {
-          "optional": true
-        },
-        "@elastic/elasticsearch": {
-          "optional": true
-        },
-        "@getmetal/metal-sdk": {
-          "optional": true
-        },
-        "@getzep/zep-js": {
-          "optional": true
-        },
-        "@gomomento/sdk": {
-          "optional": true
-        },
-        "@google-ai/generativelanguage": {
-          "optional": true
-        },
-        "@google-cloud/storage": {
-          "optional": true
-        },
-        "@huggingface/inference": {
-          "optional": true
-        },
-        "@mozilla/readability": {
-          "optional": true
-        },
-        "@notionhq/client": {
-          "optional": true
-        },
-        "@opensearch-project/opensearch": {
-          "optional": true
-        },
-        "@pinecone-database/pinecone": {
-          "optional": true
-        },
-        "@planetscale/database": {
-          "optional": true
-        },
-        "@qdrant/js-client-rest": {
-          "optional": true
-        },
-        "@raycast/api": {
-          "optional": true
-        },
-        "@smithy/eventstream-codec": {
-          "optional": true
-        },
-        "@smithy/protocol-http": {
-          "optional": true
-        },
-        "@smithy/signature-v4": {
-          "optional": true
-        },
-        "@smithy/util-utf8": {
-          "optional": true
-        },
-        "@supabase/postgrest-js": {
-          "optional": true
-        },
-        "@supabase/supabase-js": {
-          "optional": true
-        },
-        "@tensorflow-models/universal-sentence-encoder": {
-          "optional": true
-        },
-        "@tensorflow/tfjs-converter": {
-          "optional": true
-        },
-        "@tensorflow/tfjs-core": {
-          "optional": true
-        },
-        "@upstash/redis": {
-          "optional": true
-        },
-        "@vercel/postgres": {
-          "optional": true
-        },
-        "@writerai/writer-sdk": {
-          "optional": true
-        },
-        "@xata.io/client": {
-          "optional": true
-        },
-        "@xenova/transformers": {
-          "optional": true
-        },
-        "@zilliz/milvus2-sdk-node": {
-          "optional": true
-        },
-        "apify-client": {
-          "optional": true
-        },
-        "axios": {
-          "optional": true
-        },
-        "cassandra-driver": {
-          "optional": true
-        },
-        "cheerio": {
-          "optional": true
-        },
-        "chromadb": {
-          "optional": true
-        },
-        "cohere-ai": {
-          "optional": true
-        },
-        "d3-dsv": {
-          "optional": true
-        },
-        "epub2": {
-          "optional": true
-        },
-        "faiss-node": {
-          "optional": true
-        },
-        "fast-xml-parser": {
-          "optional": true
-        },
-        "firebase-admin": {
-          "optional": true
-        },
-        "google-auth-library": {
-          "optional": true
-        },
-        "googleapis": {
-          "optional": true
-        },
-        "hnswlib-node": {
-          "optional": true
-        },
-        "html-to-text": {
-          "optional": true
-        },
-        "ignore": {
-          "optional": true
-        },
-        "ioredis": {
-          "optional": true
-        },
-        "jsdom": {
-          "optional": true
-        },
-        "llmonitor": {
-          "optional": true
-        },
-        "lodash": {
-          "optional": true
-        },
-        "mammoth": {
-          "optional": true
-        },
-        "mongodb": {
-          "optional": true
-        },
-        "mysql2": {
-          "optional": true
-        },
-        "neo4j-driver": {
-          "optional": true
-        },
-        "node-llama-cpp": {
-          "optional": true
-        },
-        "notion-to-md": {
-          "optional": true
-        },
-        "pdf-parse": {
-          "optional": true
-        },
-        "peggy": {
-          "optional": true
-        },
-        "pg": {
-          "optional": true
-        },
-        "pg-copy-streams": {
-          "optional": true
-        },
-        "pickleparser": {
-          "optional": true
-        },
-        "playwright": {
-          "optional": true
-        },
-        "portkey-ai": {
-          "optional": true
-        },
-        "puppeteer": {
-          "optional": true
-        },
-        "redis": {
-          "optional": true
-        },
-        "replicate": {
-          "optional": true
-        },
-        "sonix-speech-recognition": {
-          "optional": true
-        },
-        "srt-parser-2": {
-          "optional": true
-        },
-        "typeorm": {
-          "optional": true
-        },
-        "typesense": {
-          "optional": true
-        },
-        "usearch": {
-          "optional": true
-        },
-        "vectordb": {
-          "optional": true
-        },
-        "voy-search": {
-          "optional": true
-        },
-        "weaviate-ts-client": {
-          "optional": true
-        },
-        "web-auth-library": {
-          "optional": true
-        },
-        "youtube-transcript": {
-          "optional": true
-        },
-        "youtubei.js": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/langchainhub": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/langchainhub/-/langchainhub-0.0.6.tgz",
-      "integrity": "sha512-SW6105T+YP1cTe0yMf//7kyshCgvCTyFBMTgH2H3s9rTAR4e+78DA/BBrUL/Mt4Q5eMWui7iGuAYb3pgGsdQ9w=="
-    },
-    "node_modules/langsmith": {
-      "version": "0.0.42",
-      "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.0.42.tgz",
-      "integrity": "sha512-sFuN+e7E+pPBIRaRgFqZh/BRBWNHTZNAwi6uj4kydQawooCZYoJmM5snOkiQrhVSvAhgu6xFhLvmfvkPcKzD7w==",
-      "dependencies": {
-        "@types/uuid": "^9.0.1",
-        "commander": "^10.0.1",
-        "p-queue": "^6.6.2",
-        "p-retry": "4",
-        "uuid": "^9.0.0"
-      },
-      "bin": {
-        "langsmith": "dist/cli/main.cjs"
-      }
-    },
-    "node_modules/md5": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
-      "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
-      "dependencies": {
-        "charenc": "0.0.2",
-        "crypt": "0.0.2",
-        "is-buffer": "~1.1.6"
-      }
-    },
-    "node_modules/mime-db": {
-      "version": "1.52.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime-types": {
-      "version": "2.1.35",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "dependencies": {
-        "mime-db": "1.52.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/ml-array-mean": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/ml-array-mean/-/ml-array-mean-1.1.6.tgz",
-      "integrity": "sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ==",
-      "dependencies": {
-        "ml-array-sum": "^1.1.6"
-      }
-    },
-    "node_modules/ml-array-sum": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/ml-array-sum/-/ml-array-sum-1.1.6.tgz",
-      "integrity": "sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw==",
-      "dependencies": {
-        "is-any-array": "^2.0.0"
-      }
-    },
-    "node_modules/ml-distance": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/ml-distance/-/ml-distance-4.0.1.tgz",
-      "integrity": "sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw==",
-      "dependencies": {
-        "ml-array-mean": "^1.1.6",
-        "ml-distance-euclidean": "^2.0.0",
-        "ml-tree-similarity": "^1.0.0"
-      }
-    },
-    "node_modules/ml-distance-euclidean": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ml-distance-euclidean/-/ml-distance-euclidean-2.0.0.tgz",
-      "integrity": "sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q=="
-    },
-    "node_modules/ml-tree-similarity": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/ml-tree-similarity/-/ml-tree-similarity-1.0.0.tgz",
-      "integrity": "sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg==",
-      "dependencies": {
-        "binary-search": "^1.3.5",
-        "num-sort": "^2.0.0"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
-    },
-    "node_modules/node-domexception": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
-      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/jimmywarting"
-        },
-        {
-          "type": "github",
-          "url": "https://paypal.me/jimmywarting"
-        }
-      ],
-      "engines": {
-        "node": ">=10.5.0"
-      }
-    },
-    "node_modules/node-fetch": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
-      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
-      "dependencies": {
-        "whatwg-url": "^5.0.0"
-      },
-      "engines": {
-        "node": "4.x || >=6.0.0"
-      },
-      "peerDependencies": {
-        "encoding": "^0.1.0"
-      },
-      "peerDependenciesMeta": {
-        "encoding": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/num-sort": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/num-sort/-/num-sort-2.1.0.tgz",
-      "integrity": "sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg==",
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/object-hash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
-      "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/openai": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/openai/-/openai-4.4.0.tgz",
-      "integrity": "sha512-JN0t628Kh95T0IrXl0HdBqnlJg+4Vq0Bnh55tio+dfCnyzHvMLiWyCM9m726MAJD2YkDU4/8RQB6rNbEq9ct2w==",
-      "dependencies": {
-        "@types/node": "^18.11.18",
-        "@types/node-fetch": "^2.6.4",
-        "abort-controller": "^3.0.0",
-        "agentkeepalive": "^4.2.1",
-        "digest-fetch": "^1.3.0",
-        "form-data-encoder": "1.7.2",
-        "formdata-node": "^4.3.2",
-        "node-fetch": "^2.6.7"
-      },
-      "bin": {
-        "openai": "bin/cli"
-      }
-    },
-    "node_modules/openapi-types": {
-      "version": "12.1.3",
-      "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
-      "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="
-    },
-    "node_modules/p-finally": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-      "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/p-queue": {
-      "version": "6.6.2",
-      "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
-      "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
-      "dependencies": {
-        "eventemitter3": "^4.0.4",
-        "p-timeout": "^3.2.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-retry": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
-      "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
-      "dependencies": {
-        "@types/retry": "0.12.0",
-        "retry": "^0.13.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/p-timeout": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
-      "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
-      "dependencies": {
-        "p-finally": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/retry": {
-      "version": "0.13.1",
-      "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
-      "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
-    },
-    "node_modules/typescript": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
-      "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
-      "dev": true,
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=14.17"
-      }
-    },
-    "node_modules/uuid": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
-      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
-      "funding": [
-        "https://github.com/sponsors/broofa",
-        "https://github.com/sponsors/ctavan"
-      ],
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/web-streams-polyfill": {
-      "version": "4.0.0-beta.3",
-      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
-      "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
-    },
-    "node_modules/whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
-      "dependencies": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "node_modules/yaml": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
-      "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/zod": {
-      "version": "3.22.4",
-      "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
-      "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
-      "funding": {
-        "url": "https://github.com/sponsors/colinhacks"
-      }
-    },
-    "node_modules/zod-to-json-schema": {
-      "version": "3.21.4",
-      "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.21.4.tgz",
-      "integrity": "sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw==",
-      "peerDependencies": {
-        "zod": "^3.21.4"
-      }
-    }
-  }
-}
diff --git a/ollama/examples/langchain-typescript-simple/package.json b/ollama/examples/langchain-typescript-simple/package.json
deleted file mode 100755
index 5d6a5b8..0000000
--- a/ollama/examples/langchain-typescript-simple/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "scripts": {
-    "start": "tsx main.ts"
-  },
-  "devDependencies": {
-    "tsx": "^4.6.2",
-    "typescript": "^5.3.3"
-  },
-  "dependencies": {
-    "langchain": "^0.0.165",
-    "readline": "^1.3.0"
-  }
-}
diff --git a/ollama/examples/modelfile-mario/Modelfile b/ollama/examples/modelfile-mario/Modelfile
deleted file mode 100755
index a374708..0000000
--- a/ollama/examples/modelfile-mario/Modelfile
+++ /dev/null
@@ -1,5 +0,0 @@
-FROM llama3.1
-PARAMETER temperature 1
-SYSTEM """
-You are Mario from super mario bros, acting as an assistant.
-"""
diff --git a/ollama/examples/modelfile-mario/logo.png b/ollama/examples/modelfile-mario/logo.png
deleted file mode 100755
index 1ef2564623051121def212c7f366e55ebff0ca72..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 456296
zcmV)3K+C_0P)PyA07*naRCr#ry$76SRh2!w?!7NouIe1t_
z2T)N*L5!%Vpcp_w8B~IT==`1ej|o8(QOVsjG^uk}S66sdFWvk7)(+?1SB=j1oB6&{
zpz4Kt&pl!9wbx!}pXf`!x-N@L8M0=ED2h<6l`%Uzhd4=4t5wl#G!aJ;+U*Vo2K&%$
zcQHHLL|bWOcF@<~kC~|%!~mj_{M-MJZnujp%}}q^fH*^^
z-377?olX~heKn-rE?UhNs@1Bzo~B(yQH&&s5y!yXYzvi28Leg$w3{N$x~SJ{NZF=V8(9QYN@aAjF0w2`xtt)5Vsx_<-ENAQP2|7qhrjW2Q5+-U
zA1V8XZ$|n$e~Tjhj{aYs3lX1J|K{h}_DsH>g1_)P{9B(bMU=#HJzhVFBcy&EK>A&-
z#e2wi=q?zI&n!GyWdkr9;@>NKiqHq|5K9o#cOGvqRdqwj$(t)OM)9Q5(+Z
z5qrsZGQCGc!(-zlw%h!W+c&j>`L*S~g%#{;nSEMi8$N%_H5uXslnxU~Y=QBS!yV9dk2tG9Uv({g|DZMW@+8t*@d^
zHi-}?5jw4|I?h^2uEpHZw2pAeuv(o-jB|%(@19j*s?*FCXnndA?xb%xL-|um#A^30@PBmID?x
zq6pITcbx-1CulSk45X-4D){-YZ^K8=ya3ZXC-tHQRP%RF-w&TXnNcmH(VvHce1&6N1D;F(7t-~OOK|^c+$^d|aV6h!JsGu{U{pn;~Y(x_$-LW2<
z=X7lkEnbQ{ZoL)ztywKjbT5#~>0!^;gM)33MNx)kyMvQXIvGE>{yGH_S&CD}`tg~y
zYh|7#QG!@(6Wd#G2?an*C(dV5`=x`Sb1etJIcjkGW`kx^ULXL0kUSc%N9PW-x?RMz
zDt@+Y8-BTC7oNOe7<<}HT)KM~9`AIJA_1ZY7_JyX}JV4YIxO2TM%dOHM0!6lQJ%Od=swNwjI;*U}|du
zP?L3|1C;XDgVtc_@h6}$uv9=_lCl5Q9*NcWv2@35J|G7rnaq{&Lw9FEs62aDUXVG-
ztGat9kXO5I#@2%$yHIGam>q(a3@QKn`Cnd>B?J}L$?dro`Um^ffe;FTPP!=*p;D=e
zL!X{*2um<9&@Z21B;K5BN#wp{$wG|p+>LsF4eeGJ?M@2={r%FoiSbF)`l`YjG-etS
z@zX)i%uJ(PE}^g9hq>9=fUvm0`2A|7ikJ@;XM%$E?3qUYKn)QR%r+WwO)?LhZFKx(
z8EE{Z;zE41sA*@?|Juo0mc$>f-a*-V`n&rFZ<>d
zc*_}Y!Ca?_r4ew!GY-LtOBNz(chG8gQSGatO=p#qaKj_paMm67V6!n%2ONALuKmt;
zaLALN64)e~6raET3`OwffUjr5^*n9Q4C`4RHmid^EJ*Q7=BJviFz
zK)AJIUGHyW0mS(mz$PPMAu@h9HI3^Z-G;v!8$`F;!ex^axUbo;Ud&L*GF-5HHU56p
za+HvwE3B&maA)ScUm0vkdwarp2Vx3j)T3KyVlOzG>MU-UI8JxS#3Z^`Bh*bw*d9mt
z
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

e zFcDSpg@^9PSGI4#jC`N%PSMZEdhueMy>6{+!Ax1Jp5}xV;3&otqa4fmBwC?_06?n( z$}z#D!8<9kN)=~qdt@)yLUs$Yq5{f#%^)RRxf%*?Dj zz+trtzH-pPIB>8mXGn+y%j15FXrTgzK<8UH!i zz}Xw`#TJ4@Uo+y@z5F;+0SUTGmSN;ICm~t0T22kj+Fg{b$d4fyRFVh-aYxp58?5hP z;4k9&0+91`*t*7COXi*QgRCha7X2Kxcv=ik84jHZIyY?>z?Xh~eb!&8O7zXhnM&M= zi9M)QD^hTWj(&3Y6vlW&BVdQ?7=6xt`~3r$+A}4zJ{Q;Y^b|%$Mg$x%dMB9Rk*Q<_ z=;R41s5M|IUhX62oT3nr_u?vHJphUW*=nBRC$wURO8*Kfr3#uY&C(GBxJH5BA=2Sz zSjA9sa|9wXsWMgnvw%^XMw5pts1`s|0G5L(*c|CETL3woUKG4&)K|>a%?A&~Ian}h zX84?~%?oh&_d`HcbWq+Fr(vA!bx3H2!52_yzX1SW10JpUgm5uo&TObRP{pkqoxN>? zf*+^K)j23c&z-+GYGVS#96BPm)9n1JL11VV81=R~(cKZMK-1iUE%dNu#{0>%40%oL zLV+R!MDD=FAKPIZ&ZHEh{#+dB(}NCH&AK#C5~~&=3&<_YTqW1pU+=@ezUPy;{;D4Y z)Z6&Wx!P{+ADAHg3REm8P>-~(sl!yo>z>Qxv$Br$IJ)h}@L(Z`}O z*FayI;ljfY!0QiRjkwiT#XoqIHJcJ+dmFgoo(J)TdmqA9R_&y$DA6dCMOV%~a2<|W zwG8$4tT=ndP~6JIXQlHZz-RFhWg@khiLx;Y4%89nY*fw`Xge4!YkEoNgPhAQN8;+? zI8wfqV`M@rKgp5nmfcCiC424dJa?J8L3dGbJ$63B-XxY8Kn-y{X)`16O|5(`*c@`^U zo5MacR&rBqoaWRm9Vs95anE1Z^;pb-_FC`o*F2*f0E%^r2s{oO461#l);6l zr(LWs$9V6yhp>nF>slZF?YrN`F-IS(M_JQpM8KJEc`Lqr>DOf8Keexdt6un2tRAU| z@}I_4&^>hm%?>{OyY=|`BU>Q#?IH>TyR!Z0$l*bp{a1(LDfJS{?K#N_)A)3yrah^C z%_-_ER)-ZLe0Lna6DCwp)cmuTc(uEF{CA7hJ}Iy@!BjzGs>{VAbOlm$L{vQ2 zYZa*xQjQY==+3No%1+qgNE4ontnRZcTABD3N6cCX?kTe0c z6Xgot^T0#+*0wwaaMbay!nId_2i20L0QRyCIlz|Zl<|mh+wXpdV~#!syLR#T=nRVi zeEGlw@!XM7X_pxIaBwAS8R&P#wt1C81M~if3bfrh7M*&p164*qe}Z1X*S?q)6{s3|PVn9Fo%re2t$59nbjHTTRKZ_~}zPk1xJb$!L<`(C)*j)k0 z#>56Amj@DAa*0KCOO9Kr^*z+`^YaQh*ed{_7(f zaP9awI$X%!PgXRF*I^2)Tdtz-1<%LmkuO0@wz=xsrFHaLV z++jI!ro87E5ET4Orz1Lma;bvHwr!Vf@EY0WSVZ#|JP!Dm*Jh;M8O4wVAQBOW%58Tn zL&)-iqNvw$x&!?+aimnbQhdjVg;71X<_!!CNTohf^}3CZ`S_;f*?E0Bc>(~6^5lRX zp(#|H$GyOe64;B(-81SZNZ?S4z%WT8ATiF9cdiJ}XLG2dMw!ZYx3pRSHF5Q`806qIDL-pHQx?$vS14L@1|uX0m2C|Lj)0>y2j%@C_z1j<7Jw z@WJ5~IHXiVEspV{<|IBdu}xI-t5@%f8*lsp4m|i^6OJW#k1Pd^allv~mwB$WuAQWYELGMs8OY zH;^5sJtJ(55}daHUO=J0{(gLKd|c8ruC3v|qqnq61NHy_AOJ~3K~%5U2WPI_A0rW? zFP2x<_>9OW5i{16`U@0wb)v3m0J`W_s(9yy2l1Wl+r!Fu#cTc!-@Wn*Nt^1ivB9F` z&cnf&wUPA@-u8}n;wu+l9IV322K(`;gVtdoV}3F&RqraVDOOoM|$#JZonGWVt zb^^q}r}kfm<3{>biDC0g;Hecg(oB*`E{(;=`_4qi);qzD`ED$)Wm4GP6CAa#+>jnK zn~_g172Zi&Rp%tvo%bs zTdOu`?mBf4)Unuf^@$ahdro%;&lOJdDy}+@h=N-zT)`Ud!n!d2dSs?fr1{6)7QXIg zC`5JodAk&6NCf!#l7%;Ca5skElETB7?9Md-Pgn)A<(2KFdY4P}0A zw$s#l9b^7n;qPE4AOr32aEONO>DT^ncEk63TgUm)i*`tqt9+%jH1A0|ZlH#XKXWNA z{p2@#JCY~Mk@_83j=^$-cBz6dj6aSaH>M>=`|1;p!?&*dmK-_CrgMH?_Kk1gjsN&o zsZ_W)>)`t59EKxSE=0uA)}*a#eRyDU7VrP{pYX#S6KEN@qT^l|1LqvR4kxZyhLP43 zx~Y+eVmLL5(ww|iAQMHfPDY8e4NM6rqBD{5+AIdvL2I^+RW{UQtLP1}(gi1NlBfD)KN?^%~fFWIFz|7N8!J6B8^9a!6 zRV&~lItQzL@2r`K8JR{%BWy+)7p%Vz*N*SBLP-j4hcn=vD_7$!`|XGRF1Ize&EfKU z8jOftWyCFgN}*sEt#So#-S9w99e}_4`_pmd*S@Or$lC2|B!q3jv8uBBSGU}Z6JB)! zwr|}g-x!L3kF8vV*Q{J5ng*#RX8=p;pym{1h}=a(Q5Y~^H(~My2RlzQ?5Q4O;AQCi zvlb-_(_oeJ?#9ao7g3%Bj)x}s~MiXdS9He&tfDU z9^yuk8Vl{XZS-oSI&rlAN3U%x+TReY6#$Ju2XW-NO;$UWds%HrBOZ~ zW!qznZn+OPj*sKqP4{A(FfOX>SKy^~SIW`R5wF+>i%&Tj*`mehv^C%*fGedyIm@tS z|0Q@}(^kY0lL87iq+KFnR|Znp9S8HaQ%BC+L58_z8wveosF2Gh8vwZE=IiA&K%SmQ z2g*{sq~b`!jgRk^3SG?OGy2vFe7bj$&UpNn?`sZ?S}Llu2G8Wp>C2atwFuF7;dz4oE|eDz7QdH>aWD{`*ZS6S_`&4v z-ALJh)|9)ys0*bmk%#OsTyHRoZ$VB zKZwVqnn;Fo-uEx~$VWdSku-5WIt|b4hAYLCtDN)VM ziz)!!c8b<)R|LF_^ivACEJ2_`NbTI-(z1TV5OWps!#+P8T)E5jd+TWAn@!ojnhN4r zuog+JR+0i_Uc*8oPTSdIhC2wtT+sPMGtf?$lN}3%&joFW9P+>|!(}|0M)=@;_u|IM z-D3YG?u$|Z0dHTu3TLj~9|N5^iQp_A6(#S^~`xiamt#qq zV5XemiiutL<>a1x%|wwnzSk~Zjt}j(67`N2&5;wq&QxuDQ8q_O3Q#e?I;7` zrK9~ApO{A13iIjuEs6ktsmB2;f=R{sb4wp7`oZBrskP1D838Z?XReN^0vZICBqmT` zgP9H>fZ*wSa*QvjQ3_R>E!ncCR5wL_Z8>U`=>Qf5;+izqRskO?4)Sx<4p8MU zClOYtX3QjiPt5^;C)i+noz9mjN90r%WfYnOA2r^CouMaA2{Jb!k)HSLl%kVKUTMjq zUb-}Ah^+8-0r6#^OyjsiXnf-{AhJr1jfhA+_cHrINiY@7Q%lisFfZiaiI zgPH7re{w&s-v|Jw$Ay_e^1b-(1`GhmHBB9^hgswcQ*{Qe2gr;6u>Vv(W9b5mzL}6= zt!sisk=WRYd}hjm;m_F%7cP2Ar6?XNJcK@6ppT1V#ugf%5JW_Nwt#{Ybwcu~pli^6 z<$+W3ev;t6dp6)5r@a&7+gXIe5Jd!x#SzXMU4nJxKE&l1ccF_9Zr+5cEJh_s@U1Jq zjuTFNjjS^Q>4!FL!gHU06t+C}2>P-vE;w)v{_&}+5H;zzt9X2_h4=pM9$de5x9lsH zd!-qkJ2r@qKI3p4#)Gh?C)8*P<;WvpB6R6EyBR7>BUqI-P085yI)b$>&}Id|*$(EW zTS(j5ZyM^u)&hqp~fQPl8yKFg5U%5<9nUoX{YY+IY0kKKC)=Wv! z3jo}sxYI1~5FR<_!|skRcf8)wVN7l6i-R_2<{H|c&Q9XX4?Kuhk1fTjavd{q7gx_r z;@@{u$KcZ{1}iPRcxVh49dZCh(~gcG$ICK`QsvIrBez@1Toq>4{HD$a1ZETR8yCdg z@?JscU|>IJ3_`k4=Z(bol3MOay$4Ad#}#Z&%lN>9cj3Azu1Ecn%q?Su*hD=wu!?~f zy$GW(cpf?lcLLcC8L4fPAfvx^Gi>eVb;y#*Ay3pIs18v6k?ppf4qkBRTKw^Whq0&K z6>!2InUN|YLUie^H)I*NegrX-4z-XK~_ofsA(vtw0dmzou1;#!7 z1OPPHybfQ}<9AhU&-X=8SSrijeWnly40t^$%wr)PSpi`h*cNtF63KZ0BGQvXKqxTM zDuNtOA|MtYDwVklfX5QIL{~tDpjxg9v%&8$WgxVaoam+MXB`Y@#|ku=9ikANaSr=b zoaSOR_w2TCibgGGn+@xQZ7M-y8J1ZO6(6EybI8G9*{bs3pl6=vZar_ar5UV^>Xh|g z;gqr>=NBNZnwtO{iqxr5igX$-lnl(GA#>B`STt#39YdUfVX^Bg^=8bAZQ1kv{}PR= zDa@T|?o*9X$^n-~uZ0SZ{@Fq#;18yI*-h*jqC*|maMpnAIDU}M&8eWXWQ5mJaD!w-}fv@h`CZ~uk99w|@{J%fJ z!G|1bD*OmH+;Agaed4Kd%HZ;>gYQ4{P#m#*5bYFrycyyA-`tI>ckV$`4nE=uWf@Ld zJdA&N+M!s@rOyh1tR$H7{CWxs%>j$Jj_tKQ*Quu3Xrw7(YBf7(PB+nRh=NZ`3I}Rc zpVNK3v&X%TJO^AdZUyCi?!=tk3SE?=0t3W>5i0l?P4l?`j$^H9yHc5HMrsCBBu3*# z9g|d#D^{nZ081*$xkxM|c*Fgr9=nzc3I~Wuo>vmt3I5nj@!q@d#P3?O$^uAVrdR^t zytN17ghk6x>&{Al`&K||Erey@OiokmC?z=YPj}&t>0I>okqbVKbI(322LQQV%MS6$ z#j#tqZp8^FoQPX~eX}|Q08g)%anS+mZ~%qY@}iyd5Ga0k`+PIkTLx_7?|SNOLa^G`EoRN6yfJ{Q@C*bdc0y}F%GT{q8W8?ZL5K6c5Exc z4xz`N+&_S?J?TK~Qxp_)K8kM0gu=GNBH#Kq51905o$@Cxf+|k|m~}KWkuP$$<-X?i zb8aC`d>2wvWUI7tAvHHVP4f0e18>`SH|}FKE$VPwcqxph7P4Zhtur)?MaLhD`jeg_ z6)AZKIXakqC_+lN=?2Q<7?oNHbFq4g|y(kQnkk_qUxnt1*JtMTy8No<;&5+>e( zF4Gjkethxg*JQH&z*N^f6_6E%cymT1a?GhI=PA@{&dv$CW-S2b`x*H&>K8h`)mBG8 zz+JO>p4T0=6zGBK3FJh;PDh+EsXZE2()?N=XjZ^NIVoXkYDS`e*|NvOiYlxR-I7R& zB0)XvPZx-6JFKx{U|F;PlArZcyqG_~_N-!qR^b4pr~s1>6qAowBx5J%oSYt@Kb*-Nn% z>^s3izO_%k6i$+|rOkDnAGhm$pq~vz=n8cYd^?JfULj&snm_n`J65%Dil1-MvqOKv zLNx@g+6;5Af%>)zVWvq4YKy|&Ti=o3l>_DZdde5)ng#*^)x`MeT)GAVz%XV)wG>tf zFG_I!xu3#yS6-h37b*Rl;^e*|ymn+E>MWd9ujAuWTku~Kd(g=e9RB3P@Si{Z35G^S z!f9v!`mg_r^FI0sIeG3W^)mkL*-ypN{s@mZTKL%Q8}PkddoatQ11zG23~ySy0`FM2 z9~QJ`kuo1Gls^!6co2+Iz)~ex#$6*7sV&aF>~JSd8*?)R_idqSS==OGUYnN%rgfeb zRR+iCf$-iF0fQn7?c23-DxsHE2nA+jj=R?}kZw$$2oGaDlYynctCd(-0R}L9UH->3 zi%j0UAd2Qn$^PZFJ=CO|S+|sc;8W&V+j@^qRK_i{Eu3}FpKxERsZpPdc8XOA@bQBV z!LbV$A!;=(-zt=&9umb{rYSZjF^>P^A926bMd443uYc=uyy3Ldv^~WI>kGvkE9cw$ z&V4^V{mIXSeD4T=vzIK#>8q9qZQkJ)Ql@bPtOX9B$Ds!n$83|2UAT22rBnJmpax6{619g?CYaN7)k-Wp@f4&>m#fp4 z-7TyUpw3&3iw3W9$}Nu+=I#MwndDpweuU!FZX3%hHO$Vn!32x=%D{9f@Q=QH%MY?@ zlAvKUI}hMtX8S<#R0aSIa$oI8;aID)6`}@SHvv`3V@-y2IrzF(?4P+2Bu-kYx0Dop14J-N+ z%fm_GACoTAh%@?^t$(bi+-k|a2ry)!v62^YmlOrk9HKZxL(MWMg>7rv?-s2(9psZ{ zULGj~m8L0BV_Fd070|Q_tz5ui4mF1kJw+{^F#T?OWAho6qjB}@h8FFf9u(*t&w)u$ z{~DB6fn>qa7q$xpA(nKKIdhr7xz0cVkx^a+p;o>NqKHm%h!cQ_e7~?W!D?L-e2P&K zs#C|%J{qC>I zMhkB|>1|kl_kG^e(l;Y;?4$P zACTd}D8=!=|05n|O%l?-Miaf3s>i@Uaj~uubE9<(|t81c6S&PQ%c^~F*Aa_E+KzM)WOSouA!td^bf<3fx3D*&p)uRso zoheu?F?DOJfsa109?u>e!*lw_5JxTiw9~}bHb36OO>n)9mJ(ci-~o8?&=9gNZNH@q z1H{gA^&Z5SxeL3ieA;@j|2mC%$2XxxJhHU@qugg{`mii@2AlrD- zRDNfkpY3CgUn&r$+-jsp154B=209bgfcgNUA8Hc#7E=IZEx2`vBM{ON1`0fCJL9;kS3}lB0vqV71L@S7*P%-0FJ>! zqFV~76%YnM&uh?_UE3;Kw`5PeF@0h0x}MO+oUW8wX0+91P>`V=)o{c31m3sdZfuic zK-SoZ^%|F76G_uzy0u%g$t0daZEkP+AZv+u@O<>ul?AsMe(Mm zyNjb9`q{^|kTNVXGJxf)r+kL}!!O}loh zUu7PV_Ep9uLG-1cUz15)?Y^2gX`Tx}JwS(Lcx79iMaP*&Lv;}e>OTK!wT6lD3G@y0 z$s%H;-q&9f^)L-3QwDU_WCYkzlM|C7+7po;Yi3JrfwsKHbc0mv%k(-!!vpdi9t0$5 zfySHw2%;Q<4qjhRK+5FUU^*fK0olQjP{W`_703#(-L6#-YS&f79(nsjC{lo7TVTEg zO~FDwqa29^S|&JSOBWPYQ&8EPQ}XRb+A(O~?xfI~rA@83l!IAf)dCooml$3rOB7co0uX z1F^pKwL zE7#E@J2kJy+Eoixc+U2leSa5^1t6QYS@#Ng~D|rVfBCh8Sd~%z)XMHfE<<5(!XjsccA2 ztE~1yR~2wfMv^8;MUu2#XiedI3_JPYBl70 zCimd9*S{V&{@{n&n5 zbSXzW^?z}gxQgGK!`>6?XC!RZWuVE6b zsLjco!gnNPO)(}>wPmXIr+|-Q_H;wU@;|pR$ zm;UAk*69>_p1F1w@9|@PwaQRaqJLK9qd0GNmW6#ZLX$0jgWR^DIb+iGJlSt>Xh1}R zdstGK1%9Nu8O1uJ_UH6e!Pz zgKeWtEMp6JAi1?eiD0pKqfHb1jdih0^N* z1jVc5^qV+Sr`p|$inG&*!zm-a5-JUf19q{JIr6aP3MSCnFZpS6_i|m&j};;$Pj?3g zZ`&S=X#n$gI-z><4SIkE4VmWqbkT{9#1@n;K>b6vJ_VjVUtFPJi@6TDp|#xddiiyn zYVk#)7Z<=}rB+!(mMJMcoW^!@5Ez){A^oc?s7ndGFNo_5sxaq zbLHhY_7%s8qew~>{QizR@V75H8sifa^1Mfk4B!vDCsoJ?U_qAQyuVt9SMReJB^FPy z@^}OQv;~~&oVVQn%dr*X3$BL_8WT-)+g1kI(o)i^#o*8ZT8~?B!`vJH7yR;n8~GP0 z;-bUJuh{EUd=3}y;jYR7h?;ygzG8!9P32BRuc*dQM3G`EVhK`c>(p*(!CHPzv7y-p zZjqGI$hOa0;s63k)_yPX#AVEus`&aNkKyx=Zp4J;c4@>30$#OX1fM+cFpN=zEY%ki zbj#WQ!`yp-Szeas!}sauOmEu@Y+>15stAa^R|JhEVxrMlVhf_8Vl;_HP3#g75%V_~ zqhbpJ8a0TBR6&Y#cG)t!Y@aQ&(`QcouKOwP?>%Q`fh6DmyS}+DWoPEhufFe7?&p5) z2fsLU2=Cgk2~Ghd`SaFWZ$Wowm%8HMi}jlLw;%iX$MKaff7xLHS%aq+a`^K4by%0@ z$X_FJ8oHJ-XBfB>jsisP)gi$qGMgH!P+;*V>E_S#gpu^HD+-_hhR0r|sJ@9f^7IO|S*_4ZZ#N{Q6_iMhR%i(r_sVHU+T8+Lpb1ihV@Yoxh7Ju&HwtZ)Cpcnf={GL^-A@{n*Y!4= z*n+XvM0G#c0bmwAHad>3?oMImI}$)hv0R>!EZb}LG@h*S^ZMwF1#V@=Rjs0EB?kUI z&&!em9V*)k`9wOpI>fm)^R`bTG&N zQl3#H7X*^??g8Cx#_E>$sUjmT#^GvZJ{i!5^{8{Str3WGkuJV%vH-aSCmk6lt1*j+ zgBdV4Zu;MdL2c*qSS7>|a_tUy`(GvSx}|pEb?Q3tP3pmo{wyH?x;yvUty@z^6B1=U zzaCk#E~Meoags=RWU3n=JU=hD*r~zhCH|b+6yB~#{fqa$=>vG+ z?guR|(f8Mr%itaDT{xq?NB-SYEaIQ{?81-6Db7>JqDAxZpV#~cjyvIGanqSx0XN@z zE6zUqH5eTk(LEzl0n`{xqrFdrv?md4VG{EalyLv=$&D?r;J)Li_3TI!N<34hf@Hb`}`N+SHJwF zmM=p9;8NIWeB-iz!Ta9#9?SIf2`vKfxfLsM_Phbq>t!K&3Mwv>5^b)7Bmy1+`O9g3 zf8mt`bCZNt?)>$IN5NU}{s|HzTRCL2Zpkb=w>3t`ovGLHP_2xQY}$wwxi-AMXCZnr z4cwQm;M3c;V?s!o$@(Hr{QRzNeEqmJ=$lbqyv(mKo}IR`+T4d=KoclYc{^qsU7a+b z9U-h~TEk&|H-gZK58$ThDb!TK zC!lbm-pD(Zsex_iIQu2&JMB5Ba6EOHWIvsTDZDi!KFZ|INMTiwaY@o^Slr)_y+a43 zU6?*u%icT(RVqmWy!EOE>kASA*BjzonVD1Mr_|9VB$|=oQM8rV%g+)3O9hkw=FMq) zU1g@C2bGLFD-b?2bZ#7?2OKcO3!a>sLU&iEkp2k6D>0Cq1CAdqBg?29DQP35!!Ne6 z{Vy%01J*BiJpMe(6ii5fQxXKQi-60990isr#OVv6kTRtT`OAw9%x{|=Z?$NFLETC4 z0a@pR)POC*3e)-mGLQrT@d}a*)x4uFu?P(aQDjSn)wKp3x{6+=JMNertV2>FQlXK3 zbeWn%v^vjR=&qtANzf9b5boFo%D0Hzlv2XZOe*}gxk6MDXNXQf)Ws^;ft3JcvD!Y> zJBc=<8(wY-gX!b)iFAC_2;-*3AuGwt2rUdcMeIo>WceG_f6zfQ(q}JAK}lKsQ?3)4 zVMnNr+Vn&fygk%L=5P&(p%Gyh8=6B$K*%?n$Ka!bc-No59|!gw($Tl_(Cb)~&*EbX z7GVkU=xQ|3)7g%{-LW0lPfVg#uVVGO6}a+;Kfv0x$MZ^&%@*;8JMY3vUUsGi0G^RC zbFDXU{_5p8|M;VkA0O9BgT+F!to#SmP~cV6Q<$2V!OVC?+L4@Fq1kZKC$A*{|8j>h z+gry!Y5r|Y^h?b5tRu`3030chP)|6^E;s)msz>WDqCaRlaC7*;Pl+O$p+cf5P|8Z# zGs_ps5}_+x$`n5e`fyuueu5fxnIcF%1wPe!8pEj^zP@7+m+jqwi6{u@Yyj_EHXk2f zxDLhYG{y>bTr{{7U){GS1OTr;=Nw$|z3r+7eiw& zYT^@>dbm1+4{h9l<(UG`>06B64De{ChEHtUhOvmB!Bf%Mom?v6UyfUgl~UE?yVNW= z=#E6?O0l+)P3ON=&fV5WfV!G%oK5y8Mr_4tI1=kiEMor0Isr{fP>G>Zh7)Q(g9CQD z>3k0A9A10yFh26w2J93eD(eLBSpoE=l8B^%qn4omwXZ{A=_(QY;o8*S>9gQERvMO$ zNcPvj?`n-2mi6~z_ue7Yvsq1qZGA|=kg@8exBRq0VgUbuj?`K5G_axzz&YYMM#|Ln zFH45)us)r3yJ+)6pmvrA$jtBQ?Fn+i6iQ(>&-Oh2o52H70`d)5V&KDPz`*m7d?*8g zO3EEj=|Yo6lzY^+Kk4&#Ca<;hDSNgdx&V$I5INB7P&d8IMz*h**C7kpkzgC_qVRuW zTEg;9M${?HD$Mn@;DdLvxTfVGH7vWK!Ps6k!1e`M=OI= zGzfl{!w(>+p#-v+EtrU&m)nwL!zjF`WdXGk&Y*Xnp1_7~bkt#ox|K&LR!#{U z+pa;5M^9~B6dB;upzb!`H-kTQ_9Vp|Iy{Eq0|&5a!&dCxwHt@_AH>M;FvdnkWsOaX z(Jg^sp%3@o0H{`vE;bm=0@8|V{cY5szF$QQDbVolFXYD-Pz?{^}$^9ex>(lCp_(b!7Pr zBooX^)<1c83iT={#A#hobkmI?>?ns4GOfqF$+#yh`PO{jmtt7G7JMe3i(uIJnE$T_ z0IdN+OT-Y)7o~Exw;d&r(xB`Qeul|R4y9ri>>_aTu5eh)fyl~bcM$_cia3#=B^87; zhSC{)ac~oUaBv@{B%@}gTEjpc_`3y5@MlM@#At02pWL(+-ya*WVJ|3BXQN4)ygufb#6w}l&}s>(b1I`RHhYcRlCFxQ|Y58eWoIJRVdqt9XRa*4h< zw>rsFoTE!AF$3|(^xu~8hf1Hf10@V2<>6?wDf|Rxznkl2oV)R1EJ_vd=Y31ip8+1r z0Uz166(dBkT9gV_G1msuF1O z;zR-HlTUdH=D+gQs1>`=FcGhOt{|M08Fsgsq_@VwOooV1R*}u8Fi>pA;jsx!3sGAW zXtC2e7?%OSRSibCT1HCC6rzdANpx~zpJYBtisHZNYWoZt_(dq5hP+l$NWQ(JB(?qu)rqVYM+ePTJ&q1`g+3mGfdV@L*d4&&!Gimq)L0zs` zK%rEWGT55+tFV6kF?jm3pN3Uyk3nBgpTN4*rTE5${|6U-{t{u-6L#Y@Q~vj~LJ=RF zw;1^fu(VV{y^z8=n>S*M1R-@i=cUiYPpzg{M zt$^>Gak7Z~q$`THv5Abl0GUV5+98E}swqr!H0V@SHn*}gu3P0cPo&U^4c@o_#GmQb+P$?^Qpo8#-S-jiy8IZsmq zmGvcym_lf2lw4`h*yQS0gk*sl+0&`47?9TIPcB}@N*K{?2111kDtXSKmG}^W4hMU*tBUA&UxdTaL?U;2=_(jd3Jjn zK6%V)EH9QsBuZ>5-<^z*2$|mGFCf|FS68vT03?$j7 zqMlI=K9xb064Z@4wlykv@1u{PyOG0N`xawSE{&b}6h6FdD-MzW)e-;t= zXNQ?)Blz0nMwitMcF>=!*cxr?)S{}|GPgyx%EJQI+lXzQDU^m?Xv32NPr&_yZBiSv ztfzG%wMQ!c2$c*;MKA94!CDm`+VBu=oS=9VNv6@P0OK?<(Wtexq5G9*qVx3UVum7P zjXH`%*x6kt^976p#&;c%+XjwWGJsW`UD$JQ6dMm5KqgPJJKnhmroj=G zDz}@HS|VZov5_%k*-u+2V))=;lw@qLX4I_d^I>XMozTnDHY`$WcM?(CuxcZLwlP_3r|i@39Lar z0--v}7W3h=%fMT}bgZwU8w#5ktYd_kc;R?%>dsoBLS>BmTxaQ>jGVTjF42YwODb__ zv9(L0*U0II<>@(q8@9-C4HNPN2f%Pz$? zke4Ey8xavA95m2B3&=#0S%l{ll|0N=1Okl)EK25-AWM>9PL^a42n-!Kgxh{|JMO>t z9{ll+dvI{?5E@k2`v2&w&{4wjRm*YGiRph&I^57>6H_?njc>(oufJaI zh*{sqk6wy%k6i{#QX7LKfN4lr&d6zdRVFL!e%AUM463CJz$tV@h*W{j+uGI8N9)U% zhsC~;YmoELk+{$CvpB14c@g1Ma~-MK42QrpT*MLnCWh~x#Cvbbccc6DOijXk>yptr zu0ppg38)@Q4h5DYy=#C3Dt7-F<32+&s6nzjIX7VQBlyL{VO0YZS?d~BXEON5b<1(l zqkC~{SqBVLL*kOlzJd3={T%|=a-9$D+lx2<#b4sOU;kIQGZr|{%;)iU$E?AMw!FL) zc6&$yVSZc6;%b-@r`FOh;kGYM09v1LobZIV-=qfVX2JWFLUb9{i#k)~&$zwgv&hyP z*wLusT^lzbUjyFJzXZz*S?tcI@X^7o*jv^1GkK)MSxq6IOCxpB4L@!avRM)5VJ1&v9_#eXs;Q+C#`SqZ5_guPT4i-X}FaGPl!m4wf1C042gUXX1%y zKrdtBkiE>f=C5^qU3JR-k9+Se!gLNnoQj8fe3CN7^>bZJ%@MXBW-Z+X!TBZtg)QW$ zozI-EFUF+u8J!~953vn(BB1ZSkde#z6aq~uz0tjgV8J#1t@W-Y0Eh=Isl~DlAUn#~ zs5EGH9)&e&Ak$JVLM4NT?|B&4UV9yG_|1(txPAANF#G@aKSBq5^vY$ZS1Z`FYe)jz zMwRP3hrSx{wzdJhsL&yDo$cuic4x}?^DUcjAf?*$FMP%GaK(2oM^}4~5?+Z6G*bBV zr#^=-edR)d0vD!%Z=HBNp4C%CeR2kkYz_^Q)t z=AeV+oE>1sPQfAK)=xE?)8xA&yY|`d;7NTp4p8QLjjd5igwi#C{74OhR)F$#9dT~s zTDI1IO-PAjSt(!6VMIitm~~~c`iyD!C=yi9pxVe{W37fyY`zaSPfvvM0YkFqw&k%k zmBY4)3AxOCp$%93=m+?dvtKEX|G?gTc<+18#g$iI+2s6BD`fGxHEVFPj6RqCQQ^VL z-n1bzn!CFD)XXz+`1;F`3V858$Foh!e9e1aKI+Lpc>XFtGmEeh@egDPTFWdo?|0TK zc-N*!k*U`4uD(TB(O$&fY#J8~Zov+U)wBcv41hnlbSeIN(L!Xa6ti(fM+UZPEVcUW zS-08GR>jb$%qe()`tc)#xN$;f|87dGyaZvZ*`H_lGw-7EXJbM=R*t1_5e{7{jmbtH zUmbiDmkjOG5#8nwynUCqMczP-i2DgAW8mzwkm~G{apUdTEaolj!_K`2L+6ubtlH{I zQ85t*nqfJBqI<@-5+NX)i*wnnS4+o@$nvtcKVQJXg9nAUM?~Q8;Smw)A<<9f3fENs zUmZvq(^JgW)d5hUPt^V-w5IbXf{@qDoCF7%BhKl89jX*K%?X5gAqw(vGT6tmqiTi2 zf(Yd|lz%W?7G#0LfmqLFMo;I!>t^YISwF8!0t-qfnkW$KM(R-6ib8@9`^J^=FKar2 zx55gy1?5?;WTJ8H$sBtEk=qtWX@(8#-bP%0F+NEL#Hg6up6_;Ou>#w;E(_^ZD_WzHsX7?ytizL-l3LWhQ^j8~r zMXnPs%y#1FYzI0^ZP=Qfz?*h#!oFHr9QcaWt8w)&e~7g!*Q%xk>vq{ZZus5xc-7hG zV0vZ(%Q7ikwr)M1-qi+7PNU8sH(!u4$;9{+W~M5lvL-8#!IZC!Cbhf7`UkCs_#GvY zaCo%pJd!7!5W(km;ZMr3M=vfoqa(e{Sx!Fs;GDmU-$(Pm_2Y?qOpesdSFljt!zF8B z^Gr^-e**gx87LNWIta>Sck{yX2I>_i2|4_JW&)qs`4AqME{7n1B)C*Aj|#_?H|pr< z?!&de{x3Y^^i#2K&knrzJs-eNuemB*D>KFCXMqnMyB4Q*bRwUwqAL0(+W8@S&TcId z-wXBmCweFT`__G{kE*o~BvGOb3|uOXYe;$wqS6Em1=)edQ_G^-ZF1KKC^Ze@|9`htZ0CvPCtS61kOzKy)L7IdNY7&=gEE1~@b&qdEOUI=EEUVC%9K84=akZAoqc>vGjR%Ouy#qLfNe}# zYgdSupC_AN>h3nbU66qZxdQ z8vhyL5wL}aS-v0?1r-)jUjb+T@qX+} zO^cWZC9hxbis$02v(7|UTQ?TXTZC1|tinWn04~{(fGmQZWQ>9L;2iBG>c4+FvHvUe^FSRsg zGCABdIf~Ej*nmwU9A(eIAZR{;B}lk6w5 z1FAuw__ZWo+}91@K%<7YZQ6jbsVdGJScEm59XMP_;bU6{v0;k6{>@)}4zKL(#g~p< ziEeVzOjkg3@(nJvCOS<oZuVJ&N#o5a^ zU~MO4KtrTJDl#(fJb|o3b{<~0!Z$LL+2HSZNKkNw0V}g;v?=S?ofs10z!FGEcb=Jh zO-dcQg}=6WJg|`L(g<>TnMR6>&KY+D1ma&@jtCh;Yp`P9M^K(_2p@!NMW|qS)hY&* zz_S43Lil|po63i-nDUfCR8qQOtv{qN6xHG6#}an$IDl_{^&9xj&#wh4|2vl)9;vzOM;w8Xe3L?ax?7nP9s|-A(??%1~-ll<1>4=U^9_{mIwRX=RXTyzW8%^ z_g}srci;8La6wF~UX)GYL#tNer0x!+a~Tndp^k&JcvHnuIsmLPYQEVny-DvQDFs-d zE^w$iCXYq@k%pizjv8W;pkX6!rzFc3M`)|SHjrlDhL6fGRYZ#=fZ=o<@7%Nz2PVsS zfB!

*>T;A&XCJ9mE3@oGH`%#Q^JRot^mR`eU#(%MLJ2OZ0u{r(N$rcY*$YlDxR# z5?msb$@EX{M#D+{y*DqiR-3_($8FRJw<)=L9$)7_=(TEW65XAnb@We2<8UR54{d!2 zKcfJcN#BQ9%x*!-7U>K!>rOz|%U+IL-vDYe)6%9&HB$0bCMlE8E<5q1z(7|Cqnz-` z=TDxI`6U^jk+o@nc`E0X3GuTRT7`9(NmF{4J^LgDPEJg#JTFw&UncI!@Evug-X%ad zo?Qa0Q84Rd*+2&M$V_fJ@R}Tl$M8W0B>7Pci05bEp|b!Qf$D_g4L^VLPs02sG?d+OU+-p{Y)In_fhN9)JseD zv>6$_KI09Dt!r+~i15Sam2IW(1WSpZyLBHXgk!TUzGhsMOE>^2DFKY7>v;R7jo33b ziF5lG;)K3FOyo28)O>=nP6*+%3#Z$<7cx<(HO znvehse&QI|1ELt}3`ns?86hZ?*BzpsPpRX>a^B{l7ZWiTM7KyE;5<}#!}TIcGLx$_~b zd~Z=4GL33?cc(0@iHQlx{8_uF%x`yhmpFXZC>RxS+%E$RmJp;YAez~Asqs@th(F`; z*mg)%g6vM=u$lk>AOJ~3K~zN!Lg3Gc91tqSj;@)fO;$Guc_KGC>RAM+Wbs&a%QImZT$PN(pqLKj}p(~IMJ=A)f@ z|Ll}t51I&rc)z-?B>f-dnxme6gJeU^Mka{ar6)^DuVfC7Im_od+3QGmA88Cn@$BO~ ztJX6_s+-|5TR!vO3b?6V7$BLDxg~kp|BVfnh~mQuF~dfn!T3C3&gCP)_CW ztI-3vaA+$wiznAF>ZFn?%`c8*FA?qODB@i!R$^Uy3585uGX9LLZp&buz-Dcr`tB{u zbb%O?K95(E@^36Si0nf0vh|w6)|Xq1Nt8+Vh(O>{ir`0V+_D=Uhv3CV>5w@o0kG;_ zYhW_fz}q)Jf*oU1cz@qQoH)>jav_U<*tQL~jgHO=0QedfXLI=0v8!=<2a#rusMi5b z0w&7zLwg^s2*6xzjfQ^sJ4jMCB@@PuJ(Ozg!%e$0iVZ#CnGL2z2!Pj^L~=rRXWay+ za*ed`N+t^he16kLTsAa>vLPHg=2&gK#DJnPK!KoT=zhtW$Sqll27O;Dqd@?r{AcJF zfm2RgiCnFMdmh?>QJE#6(-c`k7cD?`0bF*=)s5QJXkQwlaX#tQAHxAkZ>yUvr*4do3slrPbsqXU~HR{j`3U$Un}uVUaZs3pS$hhSeLB zVf2RyAHmcPV~giy2@6tm;$h^4S~f?x$56LST$IPOA;NCHWZg)iEZ`Yw3_t2!XOPCs zR2AR6_;OtNy&s9(<>P*tA#=ySysdy|9=94VJL5#0cEVaL>uWh+s6V(dJ>AI|s9CFBKbLj3YVP01WU4=Xr&+A4pm&e#RgMu+! zw{-{)3?0PQVYYDT5Fn%M+P|BxI`*IO`%R39KMQ}RYA~B#R~!<^pc%;Em*u%4j?Naa zBA*wv!3Cuf268#{r3+}Qr=>?Yo7SANVy#$2<5(Z$Iu7GQ?0hyPS57VQsb@FQh5J8` zm`O(#)z?J0mnZF{Bdcoru=RlixOLX~l21PA(*?_rbm`1xN)tF1%;OQCMCovWXLQ1`9^s z;>-t!l|6P3TQ`d0cv%5$q%*c?Fiw7=%5;*jM45~7o)lGbd|zCdqXtnq(bd2GojbIy zpZD?0X;g#+n8HjZg?Dd#7#oKtaqhqZoHEdlY9WtLZyUr-BO`Mn0Db8UE;(ieUOvAc zRoZ=ry{Gn%wA>Qilv?8`z-eB|8XyHoSOboX5jb{$xdw!AowuvO!T5X5W&baT=C9 zJ(c}s9i3zaJ~_7Mk!4REbY}k~;nA=VHDE?hhtAJaQH{r;^e-bcX7c=d*7W(HN&eFZ zpbLaBJ<$PnAdHWX2{ORizx+KRwQN>C!{I==Oiqk4I|ld}@(u|7GtiJ$s&q=~A0!4c zxFF0-6oDs{X-Y2X>JgPhMb=grIZ&UC;Ou{WCP@pRMu#d=6IO<2^sQFB6%{b!rqQux zXz@l0nWY5|nlT5flhofWl9%9QRze@m%65luYd*C78I-9EA0MKDiR09W2JZceM_wtwH z%;%hlb?fFMUz-8;9K_*=HsH29AHfZq_TZtthq3q2B&G=aH<-Dv?a01Ht0)DuE5579I9fyn%z>ls&25(ui z0B0{WIWwiBB6dXly(x%_h5qMJK5?zs_^MD|!jq4^2Wea(}_WVL?uUi&Z3^WG2 zm6X(h*>S=nv1jB`;gaRVHF-0MEe5B%kgK67obibVkn|tmyJS5-sc?1RDx34y+r#lthBf+67sF) zAR=BJ@w|%2Jj*{l?M&82vS=J(7GJ~xM{HXs`=4tf--aLV+l{~5wh5!sHg7j$GYz!N z%Ag^IT308!Uj7nv9D4#}JdmjSrBF;~QJoye!X*n)>}Z}P)#Vk`7q@p5t zsc+nJRil`rBh_r2j+oN`wOx+pup#YzBE}=Fb#;OKndP$vFKU3}6H*qSQ)b^iwF3Ay zcsyq6ZS8H+_NT;&G{(oqguT!9FP@JQ!kU?zV2?wj(iv3~ILG{1*$e%mqg6G zk1bLRk2{Ls{&KeEirTgO597_}`_BF_an$aA&3H$)OFt7le+We!60}&vj+ijWXF;K% z-*2`74)-3jfGv|0r_E%(v^uBeC5;sj9*^;OUsCk;QC#{xL(KVMcsJc zoBtHAd&3K{bnyaU@*ryWKZFNwegMC?bG}R|zj!e-zgA4`AD& z5&U-J7Hm8;DWWW)$aRblYR*JPBCDup3h53Tp<5&wY_jRD8l) zh#Y;h;cebC|JxuS&K32VS`xik7uw`DY=4=RNJw7xcdkp`1=wMTc&99W|2OnOr2=8CL9O)|M>1P=@wbxMzK)!FshFVEN}heN2-4y9IJOH`I|aUVs7*&0eQJtn!@=6w*r$2L8LYYvY> z#{bxCa*Bn?_9U7@-d#O~{HmkT|BACv>*`fah#U(>DU{d}pJq~%LX|^=1PRyH6`oHz zO8Aq@Zn~;bnVAv7AFoH0_Bz7w z$$-Zv0>J=81|(!NQodj*z_W6N%s6C)+yE*RQf*5)4eqpjtZ#yEC1e|m0+ftlo7pE6 zHgAp?RExax90{GCH~K|z^uEsG=DUbD;8ZJ?b#KH8#~zKH+qYo%{(aarG=#ke z4#^Do@v$ihdi}iwEB7S)=v*J62_SO7;DBVa-c(j(Wmgy5u%^_871<&drgP{@Wu*In z#RBDT_#iEY30}Ig`mnb_`2vj7DPQMdJqCO{x;$U2@xD+8I6GHM{wxWsBWDob^qfC# z&E}$g*p%AoKA2@K^E@UFto5c+7|!Q#>Apc+aqxh&i~h@T zt8r#WKWgPE)QCuCi0e>u-j3=LuT9U`hwjABDZZc92M|494-(|?&373}n)c3;P)SAC z^v6ct^+3p!0>$lH4x_Pxt`QXi(hRkpYT$j_H{z~?$(K!)u zwBsPvT+cVzsv*JhXCz6CI(Yd}n5CdY^+e8@Hd5YA8aIqh;IB77jGbkMPWtZTm`tc_ z{5989Etf<4GoFr))1HY2JK);#QaVbLe?nP(D(kXSK>VH|N~9H#Q%9e6>5W%5STAHt zo$9Syw1NiOJ31u0rqk}~>=e05!u&)6_)%fGr)?-@@)?Rx|JPdJbOVm2s)+L)-H%G+!x5X52y}*Es9U z7ot$80gvs%hF|;^mw)G4{N~}!ph=jYE8zH22`862u%=W(FG;3^3QfjYgs1}kp~hW< zX)_gG>XW@Du1_{2>vNTK3KNYwcGoMovpR(v4<5$g_yi#?tXS5A^+zwkuJIAvde0!H zeJ=bH!TC18<3(qjj7vWKDXdw(6w{c&RK1Gv@kxx1O=91kVLZBRCpK)~gzIj&9fObU z!ju@mP@VZ7h60fzwSa(VL1#LJCHVr5&9`A)p$)5YMJ&jYTaZKEM&Z_}fomlLd2+s9 zjSv?&1P(m8Bk_e8{E)5D7$R%gGs(J30?MX)kM_Z=Jupk3KrGFi&#NhBd7LNOltj;U zZjXj6cy5B#Zw z=}6HV+P-=&qa^@J0n@QFi}t!Y4fZs%?SfA6qeO5%uh0PikAAdug_niIDW#}($Yol zKs0f$$zs_G2yZ{yNcN247QCi9n`2ipJy0WWuiYt`hsSC@ezM5ydcE5qBK9elpvCYS zSI3bF-Q-##@zSoG&+6u0zw!mnNHYWmQa7xlPR5dRYPfi7)TQP~%m#|tcKqt+H{$c3 z_%zC6M_~JV)}IF6{Q8&S{J;AMj#;q?smcUKZ@d-X{l*XR@4vep!_&ZmR0gMXbmG~C zHmq*%Krx#aA{HZMcDgjG3YST*uxA2Vz)`xkIWXaP2n9wXZDuU2zjC8gQ+1@Ob>!+a zWN8f7YIv|Qjq9g|arfa7OsDHOX7yqmbJQZ-dG8=L?m8%}e^uZ=@)w_54h_6;#Q^@{ zRWHCvC$14zFN(cL_4WhxEKur{>l&Y&!RD>Iar49X;RiqeFFd?)6Glc3KUuKhzZEEO z>2N2LH?S<9$Lc~GjxDugRlbNN={)*U8DzoOQMTbKfS#s)Jm%x8zM zO&hM|%9}r(?Azv_N7h$1@7#{R>Ci20adSSfrjrD3KkITs-Pdd6On5lKl0;5k4g&$& zuwoA1AKin08+;6ZwtO+pU3L^OJtf3HsruVEVn_6xldqhgM5)irg9WqA_A2sA&9@ZH zQ37>{(rCDwZIHQ7*k9E9iUm>s<83no z=P|}d$AwU+GX?7MSz-R$xMBW1g9Vu?=#sv*nmTy4C5jAjMuH9^07NB77*wieLplZo zSui6nuPKCJobJW01HC>cvdM!8QMK;|T|&Nr6JHrc(H2#DcC3p~+knEBX|ZYkZ7`1Z zgVr_^TXEKgsA`Bh3D4ShV#wa?k2(7Rk-;Ea0C$@jkrq zuU?C`jxON92=4g)f8q;Y{TA-ob3oYerx!Z#{LWq+*V&0K!ePR$(rGNu z6|i0qf_ALR6)-QIK~IXE?>dRh4O0lLY>y_rIL)=z5G*tq+1MZ_!FP*WkBZ$*xKtDz zH?R4}eI8FH0EjbzDAFd>S7 zlptmnPubx*#Ie)pN*6#@FP=um1%lWX$bf~%;b%xhR7FAR9jiK^%mxU$-3I^K_|2FM z=ZS(s@ySLC+sk&H^k$lJUqTr48ot-ijXiIRAVB+3D_*?NLoi^!_qCG*54z#Q8jC*= z`LPfTL;*s8!mPv)&Kuju2r1CtCq|{|P^LBQn_B~A&ja+6B425LB#Mfl#sfu8^7z_k zF2oPMmkc{;_B#sW96i4mmwfJHc*&o<7`Z|f*g1s%{Fm?J@4s~o9vhj&@>CYD?e4%! zI{Pt@ArfT*UtAy5fvBeiMpb8M_hDtI(AgZd=1NGCq#%!gfqF3fQx6804%-Oft)?`7_c7)rkhq>gmGYoO}w_Et!YZ z!aS;7?MUT2kxmyS-~cB9<}*ljbs*i}kIce(Ku-rAxqBn7y8gHL^@e+K)18mV;E&T! zT8)E;rm=0yUS#SuOjNj66SKy%T6`4VcC*p*w;p*qc1ch{w2=b)c-WqGbUu%hOPyGs zFJWn>fc{hl1yLMR5-o#4D|$B7G6RRkaP@>XmcVUK7*NmRqC7#!(`umYu?!eoBKuVaG~XZXIML-omf+_jz^PzXDb1OQTI)PQ^+hb%|45KXsnP;yiiO-*1Dh_^X;^xIY|5@_5_iGw^cJBEKE3Wbsqt9P^KNc( zuJ$+K?`#umeZXOO&tD?JjOdubaYl9jcy%k6Ai0K6tC#ocE+esW@n;nVOk^;nGGviz&@R=X}2BWnaPRq69t@8$OT3ZL& zI7L$6{frpbnnC)6r+HD-AD1^2CN)ODklVzNN+r^$YPPM;%HY$w<^mze->3H#OXi)% zbe6DP89y1^fqSddC@<{7(Bu@#qwFC_)<_&$skvfVs*X|}IIFD#f4lanIBxko)cRAX z6|zWWi)f_s(nV3HhzAL~9Esi8jz(_}Qf=)hEMA21nM3&ZZ~qkk@!LP(;lZ6)^pw?@ zx3CB6=XYWG;swapD!BK~jTo<2QB47l?HA%(DO3rK_zY#2NB7|6Ivpdi3yL`L-1;(ADc(COk(^ z1e>GD*uBqz3TTkqlte#4{1ATK5(EUqFqA*+lNLDozLoM4`?%9}v0G$o^Eu`+1?)i$ zH*VaBGml@3evWzNfHV=giCu~FdFHy%BZM!ZE3?J3hp^B0u0HD|FpD2w(&A@tAkj9l z)9RhLHik)3+cZVKRR+;4eWbD(oWJc++3!7QHW5!3^3z&2QJ%vK3D)!uQS(xpqHqaMB65;P>oFk#ixM zQ>2(!5kG5tXZDya22q>jWm2=DZqN1jI`<}($>Y}(V>oZa{n%eM^;$a>5d-<6&*L-B zX3_SnGtlw$XQSNKDKkU5y4$flU&3jt7vkQ*z1TW*NH}#YyR%Cmb@2^9Y2}^}wR2`{fH+l!|RQJUk*O0%3ot-A_(S z4T93FJSIyDWcyQ&mGy{xjzflOm=c~rP8_}>0hIvLOKBiSmBO-+3wdmH{90q?%VA*P zdI5~CWIQpomZhdVQi(?P&Uh&BfCg&4s~1M)q0t0-8iH6ik#16neeD&%nc;r;m8@BuuKuA^4UV)XEo z1gu9k-Gt{F$Tu2zNm~a#z3Moeu%H{M4x$-3AXn5nUOtB!_X`8xd=`z4B2X+M)7OPu zX9=m!eoWW%xbddj@YP>lgL@v?h6AXhYhVFh{Ol9)%JnO7`cv0p{i*9@8t2I5B(^;C z7`ATRfm`p{fZOlegvWO6#n?<)2x-BvTPey>C^cmI3^lmX0Ead1wp1GPQ)%hKII+}$ zwS_huoiCzGramTp60$xb&VXk@nvo~R3-4V7g z{2;SZ<(4-#%lWq))ULyW0-p!3&qp-etZPY!v*_ps7IE`(#_=&+uyHdcTL&iC#diSs`=!h97mMd1Ehw-h z9^Q`_fgDYtQ2f3E4MgCw5eIK@ujR+bpErryZxb)_q%ITTu%V^!{vJCSfBrn5sa#?Z0xt#ag*93BB z=1(pF9k`4OE-UliVR#}2{24Dmvw4kbrDadDa#j1|-?VqM=_pth#_BbhJ3t4|o6F@? zOTgLu#e80FIKzp6f-+PD_NSv{Yastd+7@L7fleS)xLyfgLI`YmAa6NJ!YJNd{v9hh_EtSuw2gp(BPDc5flq*M)4WGS)h1 zI)nu*PI!xLUW_sX!x1`RJmQY-OHUYp0$u!(+%Q$nb2)6he*?~c`v)<+f275t>gP+D z2EO`{cjDcD^H$WSXHeTej4yoRGFoL^;p3&BY3zjU#x_TBVwwa29PKo@g5R7D> z)s5_DS%F7dma5K5F5>rW_o4eWp;>BR5K-IwZ)_Nga6rs@uw#JltjcMWxh(dk()h2v zd-2`Z%oUZbPG(l`+6VTFmAFa#}d` zvXDcab-i2)skS1r9O9KPAl21{($Xau&DC-5!yE9mtAC1L-mw9bA~se;cV7XgtY3h) zzVrn+^X!+Rf9)C|ok#u9VT?^yu|U0&x-+5RfOZzEs4C*>;@N-ihT@EKH|_5l@s(oMiCn+F~Y-(RJU${xU-yW>Q3^ zK5UWjBqKZ_*yiLPfxP}?i~q9&ftFan&^+DMO(BY{KNp#z`lO4Lg~T(Hmi4jkz%Ul~ zccFvAEe=sfv|mLa-E&0Oq>`idgE{Pl{VMz>@$+`A{+rfg1S^%8A%m~g3+d-$9R)fw zLFS|jf=K{*G~_=hFXuzsw&1oyBl!D;^Ksg;C31+nrYG_KM>b(hlDXEe6iD@c@4SV$ zV9he*rL3z-khTJ9u$Q>m*2iGi7y}uzqJ$U?G6yRiP5~21P*7iw@*1N0tAFpo$*lWG zI1!GNDlI@Wc@27Ha32~CGXHHaq%yc`s)F}E`XIK>PzWjhiY5k%Y)uN;r#=;3XTB1( zt{$ZFSzu}!3rp>&OiW|E&b|O0R0IwI{Q6B-lD8#7K<(`%shf`+9uX$JFx_d)2)$?7 zD5O%n9Nfb%1_)I3lX1btyr}dM3840Wg&9PxE;WCNnKBtnvt>_aX|v|92m^xwN(FOJ zi?r==HUR6LG^A|jBf`M3!&GXkDTjb}z;lzEASAO|RWeOFeTUJL34Tica>9ti)xjZ# z^&MpbRwt6o-_QXM65JtZP~ojPu|sTb<&%qz0|IB%+FO+2vEkpkpl11ecj|L)4YO%2 z|;0-@YCP>J>b#Sj68hS&a3mBGT20 zsAknfU)%*|k_RXOvTaZ=C8=X-{!(M%khA_SG+!ikO@A(txxH@>04&Fp&1A3Go{s!Q zjoEW1hv{qv50s~H>er;ii%EtOL@qby%6|;&A zrw8(XY*!ZeHqjU1$JvF&!f!+7rszb|5VX!!=4duq$!Ei*wyb&!&XYT_pdtJ`apsPo zcu?VMJGK?VvGLNDivu-Xvt7Tn0kVUSJ$xV9u@$!+7{xy=S%{MtFOmRZW21_9KDYq~ zt#hk&zY!=U%Q+VL!pPYrpx)V_^7KC%si7ayCW#Iy4bEbSs65yq`T-BgBiVFBt zbSfDU0ig}*DP%ZMy&+P-bhLE%gxhtDuZrvN=N#liLn%su#k`RGh!QZ%&)PsAeuiBF zB>wRk(8+T~0JG7VDPA181X`bGJ0J}Lf6veIniwoFm>}}t$bwH-Q;h*_4`G`iqZ}d| z;^e{9v=+Hdi$Ab|MGDOS3$ZB$A z*>z@KjF1!JRR4Komwa(X`D^6j>>2~6Z)Q5Wrey!bhAgS=Y2aW4$ky|QKh|=9yaO^> z^Jz>@mT~@DK8#21zJCr|oWlG<0l&EXlQ{JiX8`;6;)ZWtg?C(Z6?WGfSd-4>Y;eM%M`Y{SqT)nYdmx@@c_N?By@l3HIJ9EgpWiwGD*O`?rvM-%dpg$KSBRpn5% z1BAtGrHLxi7|!MKi_wGl$)4TVDQadm%`do&#P#UlpgKAlz}x!!@zEv6V15>;X32`B zljj&2Jv$vggJ+6>(0QbDIW(l?)es_NHCIGw$$XTKUWiH-xaE(J;H%f)ir;P70Zv~h zNj8f*IC1{jPdx^2`HQph^cOw{^NwD^9!ixHl%OLIR5LiVV;=?|c^J3db{B5C{T|%$ z;AZR_8JG60h_wNK#SxkNls!2IbxX2`Cq}ccFVGgZ+nw(8$+?R9sDEbrt|frYqzHI_DSRcV_St6H_R4 zlu#(>_q>OyjQgc(Ajbk%#DMho^=hkNUB!UJX%Y^lh>ytq>KI3v*cVOAqcf4=K2!p< zetI&Pc`RoAI-WQ!tbTSFkOx3DH?gZ(4v{h9VxfR+CM~2zz>D$u7I;Qlo13Etz~`h63rv9@ea9=E6$0L1Y|sK8O47 ze*_=>iw|OKc(f$|P=5Ryp0*C(|G_7P^*Z>gyYRa6zlr;2rZIpFKC^H>Ue?x!1_f}4 z_E1?(f`1u{rACju6)On@Ln#;6a-jyZdk`-h(WmG|P@elAwOt-4H9HG$bCRJ%w%#Zy ztkzx`y}Isd()vX-X)0g99py=UZ)iL28XrfQA1BNgKtNq;`lixoq#Ni@HSmtUg?R76 z#qw`y3#G0GCn$1{SviYYvuRdKAdt!Wl-1-U}6;d@wHGN!Hb(A^Al*5>64J^-R@w8G8p4-)n zRp|n{`Ht&VHKIc3)MN2*eAn9klsLxtb<2C5n?D%VU#qEaS(r!ow&kzldcWOj*b~;q zCmC%VgrX{ zPd*nWy(Z*T4g8ZRG;p!}LTw=`@|yS!Efu&$vh^t+&@K=Cm%SlD2~CS7%?3e)TfK@?M>yeB;ARj!~0Qfkd&N7y--Bz zlAEqsy4saTS%oe}t{+cM|M9S2$6u%!=qBim#nc;HCf_@lnhuVAOaxSq!DPS4?v_q zol}z0d$uk!1M-?B2?u~}gX9cEYD#=40;5>3Zp;FeC1qU#NuH+<+h0rwD_RQ6;tZS- z>#HpWpyy}7&_-S^dd#6XS#qq(P z#!K5W-S9hATXb?tvDk+1edoux^dByi@=o(t3Z0oWuKxV{@q%+s!{nno@xF5}!4;40 zMy8R*U$^(*ujemDnjI?oU?tNequBVb`lNjtn_DgWJ_-I>&Kmt*f;?Fl&Vsi07YwfR zGc1TSrxpSLix#}>pfI=!5k>qYAwp6_uYxRgrW^Rd{$2RR;r$pDtFPxUQx+5p<*G6b z^aFVNym@%FaRL*)PJ{=bVZ{PcN#~8FnKgzi6?P9BOs; z0Hjfw$l$=>Hr#vjt@zn5ufuH*ZBaUU&i=8zD$@NAq{A;Af+xsFmQjd_5mIX<_$ zA1CEY7$9`cx-jP@uXbUdA`6>zI2$|E_ zvj31ylh8RGEq_MGN@&9)SZS|gi{3PARatTV93a$IEMl6qe<9)J#Hq9OkJd;;g-Rv) zUiA6NpeDR;j+{4HuPP~!&RQ}n6D{DiI6O|GpR@nz?3`Sv(!W$0tP8}(;6xlhuU-C2 z4P|Rnu}s3VTZL^bTb8Ui`Ci3^EJBku9{rpw^VkBkxHhv25gjOT>=tjw@nHxqTEk!6 z&vEG>sarJ#Kvud)$`ralTkT&=^3w&HM4!oZB@F7YX>4J7Ej)w(?zJqN*6E4*tobL| zY!RRT`!C|>-<`Yn{~0Tm;n!DOfcE(%T>g*0zy~hB3guiLPtRp=;gVJ8o1x2Ry`P!C zD$i+_W9W!v+r~0>G9c}lbS6Zmq2*o08A6N{cwFrzfjA)3quKdAx^UxY#zpJYy7MU@ z#Bvqa6G!oK0Fp>sr*b%$PvMt`_v5=myRo}Ykt&C06DOl*BKfb5`I!dZGH)T?(Z3J_ zWoj+dkY)WpTaZ$SEYk=Ll0IMl%qJI9_=v<@PL^Y542?@Ri%PMC{h17Yx?>BzyL$&V zO--XF23~9KIn*&98JuU!ntO$C1V20f0RL2?(s_90~-M$V7%l6A(XQ zbnj7c;Wrt0Gv+{>?2C2H=nK|BQl4-_rGQZ(|Dl18>>9*$_H0wEZMOD-MW0j^|bJ_*moGId#nY$LpXx!0Ihp|FGb0Q1R$#el<*tHX1 z-}#uLo^nqfQy3wz-axLAMuozCuRjaDdh77P>qnsCJ~VipRIqI-7AzTGXtmy7zHSVFlBIxG5sYX zqF9R+*c{523^{U){G4j}tAlojDD312D(6e{UVC1LGU#pdH)ZL`VoIECvZg3* zb9}Cx{8+~MZ~qV;yz{G!8AA_k$60T`9Cz*Ck9pY?{%Of-yeO4N zxi%$^lct0vL}sSy`|UY-0277oiU{bnnVpTG^$2Ef3HP1MsDrzl_^0Mw8%_N^MT}ub z1Fai?=cE*|Owu!?L69wT3Nrh$ z0p8uc2=lnsGY#a(kI4~zQ%4}JqkK=6)H#Ql=$Cfj*l;l${VT1!%);{p?5G-4yJ{Bvo6?AvBjuiLTPVkKMbk*qBJ@eqSqsc0UF= z>!l{g^q@v#e-lUZmfsL>c|dICnDB^{1E72y2Iy1*m=dD_f%*>Pq7D0tnxohHIXT3bX{^*!)1H}dy z%GqQjqo?b+oBe*S@Gt~OCVCewvnV`twAzCKM_1gD=qrsw3+Z$)vLpR8hfCdCt>OKT zK7dCiXAGZlbk|C}W`p>A(x5FCXK$HUNrU{M5dZTxmX|x@aje}o5d6- z`58Nvj=oUH$wnsBe(1n3Iy*Zg+n<@9MtfVEssNIVY@>wvdv*(y%QNWg>=c$h9W1;OkR>K5MnOeVqjumuo`Vq~ z5^j^snDHI$+OZ$!z4=`1+p()907#<^X>*AI>?ie++{a<()pHRH#C zfOU2~uW8`hOOnsZ=uQ37Sp+E=#Yw7?$Y5nkXryKcbE%mkD#d|XNMjRfxP0g_+%i6j zX^Hxi{LVuT>7Y;5(Vb13*fvE#S z$P~L!TXO>N)Dw_delpS-YIUTL$&o0W1IU(LonS%{9lk>5a$3dxz=V+^1q58=OaR7qs1#gN5T6w%h5%9KaKI)TidL@4g8 zTRVMXClW(|VUHxPQg6lfS8`waEIbkMK+A(^6?gO<=tqrH-y{ig4wE3*d^Kp`1KS5N zI5CN@uUL+GJze6&nf(3xu6_8_j-4t8JV$pXiGXMI4B!iESE7&YY?5qvLKg)tQE=zB zF1T~EkLpL7TPnl-+5SvIiU{|M(Sz9Tn7@$ZCnP9b2Wm6LMLQ2bN`CS%?D^~35C8Av zW9bM`dqnAD9S>c{R62)?cI?2{_U*)sWEx2cQ(vbBLK)i1t_~F5@J7_0dKxMdQ|M~z zMsZ{Usi`W^QAFx%H(uGuvDJ@kd}{X-sgcZ@<9{nUu}>B-;Y;@DPolTKN7VZ$Y{JFC zw!q2pNofUCCtk6^Kq)C9jEzm8y{#nef8-1J^gcR&b_q(*Fok?P2#yo=O5@+7DKFra}VZ*bJ zQk53cXzMh=fGEq~dU=cQh~t7anD=1d!I?VF+wuq=n4Hwh)09=Ww%sZ_0(d8xQ%*wXouN*Wk!W{2w^dcC)Cb%V`--V03ZNKL_t(8 z0Fw3y)l&~(bYxUESVvcf1OzM*Fk3H{N~$kzwRc(M4RzrBy~qUT^Rg-Ez^A5W1l}j2 zz+Qg+d0vQyq6k>vz@Qlu^C9<1XSoYnP^$_Dfsv!M6sFTCPtWMaXNzE10iGS(cvls0 z53eeDJ@&$*tUiH(9ZpWN1mBJ<6^IY=wiC<#;(Q{B zb~p^md$h8bn3Hq{Bgo*ssR?{%&lddZz(I`q zyccuUkt9>!LZ)U}K1qs5u^M^&YI79Ns!!l?rE2IJ5P>KfKG~D1HK<{QIyB`<7Xiau43sDWhmgz{PQ zV=EI<9a&6xkEMwMTS0tUo@Ow79e*dVC+SmE+#)x?2LCu|PYi-}75F)NJDfv9;%Gu` z+cGBeddeEl>cG1Hqu{_M1nMGjkKv0Z#FsJXV+JJ-4s?ZvMdllMVBv<(@V|%X|J1om zc70j+?=V_8a#Iq<7imDqK0X37r<5JS+SJW#ET@x7 z#pqDC!Z)mFpBrbv&WT7Jp-q+xWH^ijBqaD~a3cTpQmi14JC_&m;e&hdaHkyri~gsn zj*U?KZ;nmi4@OsEoXVZ(pjs=7GH20XW|0{&XRjrX%vpJc8OjERnmC#xWe@2u(+PJlo8i4Aohc z|BE@NnG4K*bI~ynG4z8;NJFmBp##~$HB8aKaYS8MEQc$?8P_?9@N8RuYcMLqP8`C zlMx7`HZ}Wolwx{m(blkdpD28CujCvU(Vyzz^^a~xr=8*-wrs%={fcx(^sqne;j;T4 zz>nvY4-=eObP4qYc*n-gc=_sapi4ryCr)l(`%5cvnNPwW`iA(ChVSEF+Vux0-^GLU z`c7$C7wc^S={>hK?lVl5!x_jJl^^P}7^zh7D;Vo(&(A(j`U zKYD3dh=)ENSZn%;3@p&BU*TIH{KG)NI|CS~Frbj`0VxSkIEVoQ36C9l*q*&+&Qj}f z@|Yu}N89L(S?Tp~gK4D-8ujG+vBLiHM&7VkE#?!OlEFE)mqQgc5LU96n?rD&0Ry+9 z03+KP8I12)h@Vf0J}o;4@RGsXAtH_7!jnG2?t2y>*tOUIATIgbl z&e6v4D!gV9vPZo7OJ!TT)iZ-B%ybJhr5?*^b{tAYLMb^WxdgRB0p%ozdZCDVE-(Kz z_;0a@O2T%olN0lV#Ym&jUsrie9uZcZ*YUz9xsb!XNqznA_>@j@w&`#WOViwCD8p(2H z87`HQ$4DOd<&A6bvP&<;lh&?9ZTN5yC{r|Vr6n2^5>p~Wb2toh8sw#4eE>{ z5r2?JcX0+g@45%?{l`z@8{hp2cAq$A^3R!*iL*5ZZR?Q3Gn*_8OyQhDS*9SSNmpA3 zC0nFNHu&7ofPQaaS#2Ld(1T$M$fF203jnO`PauEB8jhG{-8*8(0w+L+qp6dQAf?P7 zge@-n)HiG7c}^YYhg}^=tQqJx;PA~^>pQH(V%O%=@xtB~24ALslL-;2iw=QC2te#U zn#?n85uZVkrKO~YKi>5)%3a{yTehHDqTrk&dMo)n-m+sSK5^)X>OO?MovnQm0e^dJ z75?`0^(b{(Qko9vM0n4@a39Zg;_k1A@a=JuYHIjThS8e6)PIyK=Fd)F8b??eiY!=@ z1wbZckp&JCgnLAw>p8oJu~?Jc11rA>O2q_%ojfTpTP)$NkL<)J4;(;8`i$-TqxGw8 zy#Us%LjGm10M0lIIC>Pdd=>e66Uhf|{d`(3Q8&LJj+lOoPLMTtGW{v-%OK$Ru^9}H z3<)GbB|jQ>nIF*Anm^nA=u`>k&(6$9Ilwjf=|Bko6YivQCl`RPrK%q{1~YyJ7liid zyys@;w47khUow9hGRsi-8or+a1G@)YwwQ>4IB;tfQaFfhh1v=zT>*AXU-;pHM)oxj zM55)8EsM;-Xx8tGBF^5kO>O?ypQLU20c-9^K?njY_4Jo{CJ*UZWwc2`#lVdjUu;=zxm?BdANw5M`;LFI(V*Eec?FkWxEb$z z-Lvs)fB7Hy{^11_%D^;->8x}lgI>y$DNm$_0iHTozE8)iW(LA@4u$J8D=86wv?q1_ zWaLjb;8`#fDlPgs_89qj3>-MRwIYZ?9yQ8q=5rDlj2225%@;6|D`2ctLNn2S%QE92 zk8(~Yzwze+b-IW`FgPHw)!J2ALRcbSz~rY_(gZtmJzR5WFK(MTamqRAo=Xr3cww!9 zS52+O)JhAjq=V*29b+TI8YYPly9vIyrIB)kaZW5LVj0cv3C)v~Ac&5LhJp5SOUFQ( z!@*nuUp=r7pV_xtN(40UvhB>z2wx**f}h}N8#dw9Pq-MDZkk5DHIKsLvS=8fo=11p zB(P~M@~54H;`D0tSl;81lDuX)-Q^V=zVD~_%*VchfB(X_@Zg~X1`WpsrJXsc{0P9CEg@2jF@Om_1?0N@b>G z7cy3NT4w*G^k(H0+h{6h5hXqj8W-0>jBdpZ2==F?CpD(6J{M{{}H zc;p!Vc>BXxlCiia2LW_w7d4vr_<3hys!L3b_gNuyZ@TjU7McLq^4c|$N2PV;xf zL<0y32)H+dn`SddOy5J3x@>Jkv6jd3o+kXLtr~fLF=llk8%k#*u^iUj`K=Q%w z-KevO%os4sW?h>yy!@V}0oLuE4A7b?mzrv}2 z9U<#g%4N|E;1~4+_&Rb9eEemv%Tk0YJ<&KyfWUgG1QB{pd@VD69!rTE78$Y5lqVw4 zmOw-6@+$Na5Afm5QDLDB+HvGU(T2>yx|8om*zG}v2r!-t-~gIMc3L0M)z;_WBPSLj z&*(jN9&sq(;fB_XEQIk>^~Do$3*tyMAOPmEWtJ1+kf{K{Wkhr8!ju&T-oZdhbz zJ7oAWo9d*f2;`MRN1mx>SIk-2!bX-od&65CPL=Y%E*3dZs@uU#r;Yhu5A*G|)ZLX5 zX1Y6OnDmsQ>y6IRVymEx+Gmc!{#Hj9f`w?#JK?tqg{;y<(1YPZ5tF47CUZrsu9PrU zC}J$1M>AK%i0mm=G;^YN-)VKx%IC2=m&f&o_u%GZhecs8Gc>+3R84URz%!~t_`Qi~ zOfvIITNrCLFg8+0jzd`366AxhgoNm^o;@%lsrkyH?gH;W$G7Eqmxb7vqSvNK5G4e1 z=oV|(xzfU?4(-Kf4(-LGiz|}YIASEeja?j_9>xm^o_X3vTz1LDxM*rU8tfuUPavtb zM6bL%I)>!5(@{A69He7Spj?%i2x*aJ8zL%s9NN1d*MI7ZxaN~z$35HkpiSbR_cg{A z*q+TABzV^FC|)?c8mH&W=yY4ME=4sljNtI_F~$>oo`h%VeDcl-Hwf5*LxunO-1JoV zGuNudN@`bW!(_6X1(mdCdXFM~kC26Dk*%-4ED#v9BcAkSRwA=Z;+3PY#aC}c1hv0s z_Rd>h`{?Nz!OYP<-!o=JG|}?S710<)y+%udyyxTqETmoh)t((PDe{lku9x9JJgkhi z?WNe&>*BZXzYp6N*&m}y z&m@)5`1nb7fq)>p^_`$Z^@@A+GUY%sT=|B3!>7h09)r+(-?*`4&o3t5pY}*WwgC z2n;`WVpbe*qh7vH`g7j`*R=h8bp8$4wdZ8-s_XDLS4+an%7$+!kt8^{=7q2YmuO3e3={4 zjpVG_0Kdo3wteUzWZy?9;sTA8ui|awf9tD%WPAl@6$jrqkUd)QM2SohG^njj4$lMS zLK&aB`g;7!-@Ui54UsP*X#V<3HsUW|`XoI4uWrBt%gea1QNeEyuSQjJWg7-(yPruc zjfAt0mGEPCO`=^T-ML;sC()9@Qkr6>-NNy13;SD(IM!?9XnR>iX;#QDa6}-oG7*yI zFHq2JbEI&{IuUy1bsfe|e3f5H`SX*nL(oMiQ z9Vdz@zIfy?Zr;Byv>HZnie^Dcib@LnO0|kV8e4-^X^Q2vgOQ;s)=Z6ox|npt(j^f} zmExg|L196x)ktN|f_FR+z2g~6R!bIpB9k~J+b=#C(3#J)*0vG4=*?eTbotnI&#YXYa(HqTRVdM#tq0#Paz$yp-19eAw{lO zMUoUTw|_sr_1T;7!E3*c@87>23t4E_e_KRf09c>P;e{g;c-GJ)rVDJB}a z0T4Z=6!5kOa7k?huU@xKkREAq%@;JFPYU=y+qUBqM-STZ2LpfvMWlG!x^;NX<~2y$ zoNlMYN>xF0l42CZIX5pZvBdYszjwc2$&_-8AX@xPd=o*EyHcVeG1-%--~-&YN7#k` zO8)ipb1X9iP;SSpoEjXtbv?PIqavn}&81|>*7{rtpPD_6zkc`uEOmT%lm!Cz;rxd| zd#6-F;RP>5;nGX6yts@)V^oI$mF4DlRlDClK>GbD2xP5(Yz<`g%>_>9Pa>d>Va#m!QbF_{I-&2qY+lK;2?crN^G z?Fwi~WG#FGDOn`a^DjNmyg?Rm3xs3POkVq0-}LyF3Kb5gOqcc*qL8hC2{}glN9cl4aSAf3RojnL+92 zN`!ZKrsEE65SR;#-T`TS=Dfsmp@L6+^m@GiUGE!^0cKR4;L69Z!C(IFlktoI-C6+kQCTLESA;+`CalAPodF!2vyz86 z|M|3yW1SVuc9*f(ZDE$PFS>0kr5!AH85|IvH#UD{K*IeC_d$z5x`jhX65UqI4x$_~ zGo}3skIp0DQL2SJCdwsjsWq^s(m->(hMjW@xOvB;!ihNfOVKVG$6qehaQVb)tY_h& zwTz)!5mQscDDy@#QxddJQuVAq+43#Tp4^yH3P{asniP~#@8U*8)p!zur1b>SKUS$o zr@$xnJ%S${I{~T|YtpE9MkIgP9@hoVAFARH&U-vweAby5<7XCD&}Fb*%ps|jkT!>q zTeAx3`c=SG6A5hw;bIDc6-yFC^_GC!zjQOM`||hjr8|C#Lo4&AyfZva3JRT-FW}i@ ztMJUm1lDwwkS0n3GGD^;wTvXE+gG2iXnwf9gtN6HzL_|D$^Lb*%B%|h-PWoE0`_`U z%QPj#IEpvN6VQQZjRi-dp2Td_K#N`!ruI3f81)Z<>B*UOwzgwWIZ%cWBCz=~xjhE+ z%Y(Li7h3Af{mU!|m2^Iy_VCVK593**6ZrM937JVR=x)kR9|pxaeEGz2{Nc`ru+-J= zoY)@vIlgdg4F7QER@7S*jnne5*67LA%F7g4d7u5>19tCq@MoKmN$?3ENrPH=#7aWU?q}c!u-~zrFhg%uf#9Y7qF|!qRHd?~7nFmU#*RrpM%OveiKXeAtY?IW&psNCWU#Z`p2O9NEhgSXx{Woq$@cg5yVz zOS_*i_X`CXE<|A=*7J*$9=4eT(lsDKhhB+HE;DFfditHUEW|yM05vL;p+mwg(Afs= zp?x9Ai+o3U0uToR=3Mli1#CTw&a+Zc*hN}f5)Z1a4bPno|477uMqO&tw##I57zd|(a1^3k<8BhQjv8?{OvYo|7aSi*0OOyQ}GaWvR&De}!aU6LFDuVahpFtMR_wSrwm1)SsKsxUp{EkOrof3_7rWaXY%1q4B=X!W<7lIzvMZYk%Bfy+20?0}#hSSS|p&jnb2GCT8mfz9o|&D+P;&@}4;?|H(GX~TVSXNC zBO_?FTbP?&!0_;pIA*Ock}Q>zt^t~_;pQ-o9X%$c1&#rxt^oN091|?F1SFf+vH*|G z41Z;L$+!V+=>m`mfJHAAbR_CxyP}LAF0&1h@QkJ!GIqF7uzEj#RzoKnjb#H11~eLv zBY^M-GxaTV{vLez^L1xyzCM&4`r!AFmHVsWM{LG5?8AXbM4q>&oYDJ@WarUcR*Uan zK<>{6BU_DQtacUZpAkPH%3rgXz&}4bn*J?1dK64$P@rB@IbXq7ZoCOsz44vstgwO4 zzcg5Q<(9Sh=imEzyzrf0$Gsik1yfTvqg7S7*$gA!A(^B6&RYKlN;t|^&c+Z6d5sP$ z=YfD8PFNpuYfbpWBLk7!`S==KkT0Ru zZArOddc1*VwW1Jk3n{EHR6&{tIy~_D z3FNm-BAFgVTCXD~h(wB%r2}SVL&HF!j(zv;#QQ(+d3@%3cj3|b<3AG-r~|mPRKs&e z#_`1RsOT!Jblag`Etw-*J2}Wkf&h+J)?rJzZck<;R7xyQ>WE_A873#PQmsTO%9U0U z;QADiD3(y@JiHYwNLzdS9XkVeDwel~sC^(q4~w9$rKxXi#BqM#3iUr&6zQuo*g4_& z=ze!+m$kx0cGHj&u^8rKl_Y5BkKH#;{rk}F9eDAowK%s@6LzgmOVsiz*T{UnfIolu zVSM)J5snWyi37m3(@1)_YRhK4WNJ+G?WL$Ft)5(G+JY%jjtVkZxiPSC#cwgiS;)V|Tr(_k%!;zbt&&wn1$<^+-t-|^*? z@~X_%H6zap0>JB{L#A_O%|niqGP`E$h4$Ce0SiN)Wr5`t>Hk;tJ+^3e1tB1TP%{TE ze)j$MOzDqKpY4Eb^;4aH*815wz|SvN%YryiEQrKFY7UV7Ph-W-gBTL$-@KJVe(w)O zNst;nMH#y87u`)B2)L|80OO5y*`Hl!Tc_Vi>hFUqkBZ1%FVA2*dzELi!7cb^%AEe- zM(xWJe8akcP~SEka7a<`e-c6v0SbD4ZSitfzPU&-^!=H1T(17vySLSNg!sr z{Cuz630n_D1AHgS-@NV9NJ=_@h0as!

vZh4I0q6Zqk=gV?{kD4GO)5qn>j)c3^x zmmf03=zjrYPr?~^mSXIfm4@;|oY?67B@Df}RKjJ$QSYYd001BWNklunZsB0)^lg5!t&&8-^n{e z=Y^LD`+bHiLo3Bei)*)w$I>$1v}YT>dGKglpUDCVtNBV9VPXvFt1d%v_3237_wCQ7 zRl;gEDT$dsVSLfB7Djyw!_5&aE>fM3Dt>t^E-fj9&-cg_K85q?+yx;R8A5vlx@anAbK3{=HGz3NbPct218Hm{=xZX=WsrCv=|u=ozva&yy4L#j zXFF_I+5HKO2aVVl5PUQP~+b+Lr`)M0^nOmER2WH^6Pd+6Hog;nvd_x|h`bgV-&`pt*tsd8%}8&yk#yjWMao9DnNQldZ3fg;*i@;})X+y>maVdjBVJ<9+ww2uG0rj4yuf(`&hB}z&<>G-D->{#8G@u0)tNtMj0C2yU@mEyY9oo^Ni?D^_5^_xrmQlcpe_l z{J+E507QkX3~6goY(WgD4jf8u&!9svFDz3{d#XnI&0}-;{NW?`lXcVBLfsqTc9^=X zmwfvp+lV}&wnn=|;+Y(w027gpLs(f_mQ0(@`N-j;G7N|}gie>= z(-|);E@HSjB#xVlg&9190Zt2K@Ibcz+{`>i*w&K*^YaU+QUkzr}PqGzLLx%+*QS$(wS@#P8e4;B zmKqqPbLzDP?OQ!Df_kNd9>*@5f~5f2l9gq3W**n+abm=@NkDTY%hH5XAy&@TmrcGC zDrYW_xk3p)SXjcpJ+d9Q96cuRuKOT8I*;2!sRvwGt>6!~oQY>`T8%Mgb}S(k66DAY zND4v_O@_)y&RUP+nQPH5EFmp+WXf5-SOZE8kPX4I06In7w|zg}^^uR`3wQoE7Eh8@ z(g#Otvbm7MZ`3C7lE(E-BY8hiru}WNc*m1+VZpt`}*WklvBKRWZ9`e>kdw-Co zb?6}rR(-E)@N3&%YCf4-od+8ZU;94f&?{L|X^LG7OZfi2L->sit1u=ifU3|avmfc4 zc#p^#>lN{aM|R-ThY$UXU6liig>N}yD_*^NHHwS#(rPIGDS5+)fu2$K`+3c}!%}rF zW9EqExhY~zA+66HIEpVHK7u!IUWYBEigp1Ea>ODscNDwH2W$CN&nqCUAqcbI=q9r- z4bWsaMNypIdqtA?oyv`qh@aqxX%DZx|8DGER)xe2=gtnvdn-cP7oUyt)1E~gfG?z- z71!a{Av|=Ly^hwy>J;?hsNZ4qS$TPvv7*?*~Ic9|`n&r2O&8UEVaZ#F;|H9G}* zDVoippe{&<-RiWpm*47OQc74_5>gBqkszjgYcVf@i%Sx_ zSde!h=;v!ME>GB{Q8Vb&vOaxEArsb`c@!Lk03s?I_=}=aLTKah9T;kB5@LU0h4$R;Um%knl-TS~m0Fc9mN)_L}{3875C)@Bh-#d(7TYowx7by&0lKVo_ zU?H1s43D(!bNv~HEn|c~H$0k$>H9+aljgg@Ky<8MTOsc*>rgn5uHe=~k6_2bY|xO; z(uk9`)z5VMx<%uFM0!=_^(4ej43A;`)M~6>y$%!2F>GA32E(-m%2m$X;M7dj^k?g! zI1PT8!&&aMaD3(%zJB|y_|{$jEdhLFI>L_EcQI(~VJw%&bH`WVS4%@!O9TWxl)62v zn;5~6X>ZtumCTp&xk|mTTCS-Y>h06@>zn{tw>G#*o{KT&Sqh{xWbiEzY_WvHl`5{= zvj?BtwF{4OkH=1hpevncnqoKwp1EcOuibJEE*_mg!mb~s4Ip2sAXm<#o9m(5C?a>x z6bh$rLeiK*PILoU!|9>7vZQKpV;g|t5N^5UJ9yW}ug5L-K6q+=0Bv3hoL?y8*N3KX zacKzkGy!?Z#2;DLCXy-FZe1xl1(clxv{|%$w1YsiQ5G(Sj5?O7rMe(EVO8Pf46Tj# zmDnuvw2H>~B06QNnpt;!c>Syh9%m7f7wCIJ0;xVGE#>fmM;^m1$7k@C zjcagjW7rT+4`6+mkZ<^qwq!oV?U&rIff7JaCyv85<3{+Vwi_fPex>ZFQJ8#^m0b>& zi+JPqhw-(;Cv22=#v*V-6BdFw*aIR>1Sb>41AGnlT5BnXxBdBBaO>A^ z>2s6>u9~?VzVedCq0*kmYi`(y^QX4rjD$7QXiA-bUUU+|jt}jZQIr-1BW^QQ(N2RC z--FH(pam8PO$PQT>T{^q#!W|eV)w$Fi+*M>>PeY@RwBs|m*_I(0~vU#)321u*t&5O z9)H?-IA_Zln4X+KwLlflygD}4npxL3(wUIYe3+2b^b`6PxejTMBov=7;QM#~2seEH zCLBJZ*^(y`!KhlNHc5B2d=4)fUWMlst60TOnIuK0-NSgJjCB*EVDFxk&`9jFb)r## z*0r;40n=3%u@r@ICA^mNHOE40W2$(5D9?IZl{$Vpzkm-vv>o4^If9u1G(aD>9%pMI z!5^Kz70+9>0n^B#z;Ve1Fe98;~&k8c|R@YHGz&#$k>W@dfdn?2U^bLg?v)Ph`|hxWDT2H^T^ z_u3*J-HQ@HUtoFFc`?3M|f-=V3*TnWJAeQFDy{i!n2HP>V5g9KRvTE!o?;+lEbdWMI39d;NsD7q#gXu-T#BVi&~BuFsE`(Q^gejdhUgIdc6X4R)h!Ob6&hNOUQth zNChHz6jSvf0ql@56pI~kbhh&e@aBhh;GX#_v4BRsE=F#Ceh$qhTLe4$dBuXMX65Ab7)a2_5ls*UCbsdBgwrBX zkfaM{`Z^y#B~%sOmo`L$`PCWf9qLyA^u?XwY*8{Szf=bqZ7jRN0qSwvF28s3iyhaO zXS@Pp1i_U0?qnV~1_aHx_!h`EgGY98(jTKQSqq|}O9SWU5QOp*`XR`^ zz{fXW^g(79!q)WrB$CT+btqlI z&4(Vr?&Udwd(GtjuXX!S((!v3B>+5|=I{ufbpFrbDHlBv8>UvH$c@?Vio`JoRf&d$ zWz=G%S(=9G z%~fa!6T2sVJ@l(Hj^2=?6-=@c($1t|13GkP{{CC z+aH!yDDc1&2&$10Vi0@eLDy`-if|?*urtZvVgdIYK8nS54;N34qDEpT9kv;)K)mnt zWSt+cl<>NT?!#9P9T)VaAH>&dWn1TEtJmXAr)@xGX-W1Dkt;DjsvjO^V0h`u%eYxk zYPZk$2huu7J3(h2yi^C&EjN%{OmA@-Mf1 zHf8UnY5?RhKQ}L}eH_EP(rROLbVS-*|$U@*bc}C>H~lnERgw6!^vI5 z-zx_|I||e}X!hjNu?|}GkpaEt-`72pkp;7YTxOK~+4`n&Cn*2M!CK@{Jwrd$rq$;g zL28-RjxFIpRnMJy{Jtz=bmthCFa{%2hrb5*vD*M&j{d&b;l{^`f>^unj!Wq|R?9>9 z{B>WzRd1#iKz~;+{m1Wboy0#r?_B)pNBuO5;f;qg3c2XThK~H^m091`}Hs4TX)`KwZtNML1Jl*ID4_XNJ(dJA^vVdaPK>wSX|?0FB5XrwY0e0QVllNlLCRZn z#7Q12xjgpd6a4#*o%q6m$8eaf0v<5iJ?G)L-6wMiUNyNMFWayI8;m3<;$;lvL`0~J z9?Kb1<0zc97P-j=P%nwBu=eorq?tJs$tDJBlep)ed-0ZkxgKA+`(CuzF%bDnf8-26 z&aGDP;^rzmAsv#L4k)QIT#q(~pDzQRsNSfao9j+^8%QzRT12kU!rfNPNACDi%4myDo-Z3})N%CaQJMZnsQt*1BN!PT5uqTF2(Hy| z;`j*}IZBemv17-CG)P0mRzMm)b_j?JZ$c7ZNrDQ#mu-Di3FPkxue95A2+oi+jdvT^ zBXiP)cd(3FttJ<_z)pl>QEO-vd1L1+GhiQ&#X%3G%{>RH&hlx7_sIgG$1pJS;pRP4SYdJv>Q1s_no>Z z;vmOi?2|(JzAW3rl)h66nRo^dN-*QCiAjn=p@ciX^CP_Rb$^A0nYoi(=o2SL@%0y8 zh)>;o4?go)55F)vjasXVu0Y4xa2naXVwg3H>vPDFv)8K#G%dNsI(JW7<3#ku7~C|f zM6QmYgYV2dhKJ@(MB{g}mZwv>{_xz5Wh|c>1gVO6-05fIH=g!voV9r?($2DG{9@R; zC~yZ0L`O0!oxT}+mcKYN-DI_UqFtdzOXs=Ub=WjNB?7DXOt;%YqgX(tR=|IJ?JKzP zwy#Ocq8bbDT(Iw%btTNI6Fj*-gy#%RV_m0*N}-FP;VR~j&tbY!#k$cEWFQl%&1f%9x(nhTtLr+e`20bnxo??#BK_vhg!3s^6(qtDuL!+Il7~Ups;7%A%AN zgq+DNJtzd)J8U9jxJ(Cgz01n#^9FuN)OqLJ9A0zZeJJFLc;~8VJb7Z$boexLlqNDEM!BK8$=&=9WAN)`c)&Ky+8fkH|z!L@ZyOJs?X&|!p_v?DjItH?5Ymcx$V$h`;9V|~Ps<}+>_Z|oqb?rIQ;Eq14 zeMjrsG7$^BWN%U(E{8*VkKxM8uEefwI|mGFf>pHy-~81JaO~&|{`#)NxL|ZWR=0hU zm1c}8!J1{^{gJlcSVsY()Y0pHf&l2S4Z2|_p7Qv536|3o-=5oxpUfRK6|JmYO55DD z-Afn7Ktvzzq1M3(%}R{AYZLvcaq@RT|02Yp@Z1pZt1)iKZdb6 zIA(b=2RwiMDqKFj1!tFPlC??cg6L71^CWsm>J=nYb>!BK0;@)mG|PaEFPDp_h6qss zq5+Lj9Ghw3->`W7wUk^<+HOL$>pH7=67m~5Q%JDKYqy*F<)Zm&3(ijyxi+yrq@BeTo$6GAZrrE zW&ye;FkTGl;ZU)HD;~TL-#Bu#F967_pni8ry@HQkcp)}{#BmZ%wH;8Tuf?qDjpE*N z)Xi(fj)qFwAZV7}2%cY3F5{~wj^WDtA4EN0!c}Y6;wj@}g5D@WTSFKLkHk)7Bx&8c zUXs@H)W?(sSfO*mY>VF3xOT5AUr{vM1%0#t3-0;Z-JYNTcjbZC-FH78qbSfxIvU7`(_=VwSGG1g~fSM_+yDc+5{_AwAvg8tW)|()Fa!U zus+KGyt$&)FO!TYHl#3_&k7(PpjNAjkzb+cPs(~(P2_xed}jQVJERyPj&q4Ozhet$JW=qV2f1uK{P(s$U1JD z0tDvhmfyS>2Il5&JZ1%9zPg5Mfhi>+NnRajm~ zrHwVQ063aXu_l_uJdz$eulRmdz)(Gb$bQ&hp%5Dk zfV=J>vVSw<;=U=AszOkfA&)`if50ZWOOp4BJ#f~GB?6gWGXLkHohA>ml#>*T?KWmt zR!}LH1g&EGxxsp&f8X0yMRS6mRjuNK2lnG_JGP-i@~0C_1G=gAXE;gmwoRMyyPO|E z4jG9SB5$qaSveLhYIvmwF0Yh2qP4gf6T6EY=_ z)$L$^v4FqWu>-dpJ}!GH4*latD`l&H{q7BErBG1#K1on1>5v^}*37U^oS4Dr$S_Wv zn3MKDsvohRzh0}!O{LSPGiF~t|D|f5_UtD@8YHWKc4h{3BLWglVEKR#l68KvJsB9N zXpd#<79i;eUzPrqse$bl%B7-^3_XA#nxH~N7GFh5fEqd3LywRE9}VmqMYCLawQcSw z+7cqM#pA9k9m8>!{b&>!kM|62IRoPRo^KRF$4|vxm*Z>zs(S~e&V?rB83Y9_)ANjzw`0zix zKQQ9;_%sfwXtIC#H_yX6zjhyfGGD^aH^-2)=wwtOOjm(zCxKETf}UsjayWxh!;{p< zDp{FR`DjF~{pg;hqqyb7KFmqiN%lOrv7J~r7;p{RM!t({{K*&o5?=bE-^5U2iuDA$SJ0y&RTT+9(Z|1g>wdEF(`LnWO`b&}dYOs1`XSs|ONw ztEIfC&9N>i?XZ;HZj-3iLu)0)iKLFJ|KoGGblqC~!bPWJrBuLuM^4~9*L)1y4(-?b zChetqgEUuDfIXK_F`O^s*CwX%OKAl|-9?Nx%INkwSXypjqFBc16O%HUxy9+B-Vbjh znw1W%C5O;uA&c{qC+u~xT zKxpen@TR1PHMs;YU$YUHZQ6iM`6|#}(W#*}zddEyuv`GB9WXtNWc4sGF^Z(3Lyjmk z1ipqMRHZynYogOF;&WgAHs0~E>v8|lqo;6-I>vrWK984;OykM5Nfek2*(?+3-xe(d z20%t0Oo3&Jl@$tD?DR0#<#~3nd8C2$wK7Vf@6+{4wD#{vkj!xin^S+Etz1JTUFv)w zqgMpSJ-;U;25ecZp=-n0d$v#vg$jw3WY*b!jCs>;MftCn-pD24PwljW#a;)cTmdx_ z^+b(Y*Mh{~M!c24$ESVf3;02=gWvt>T{yI2C{*8*@Q|>FCpT*N$VC@m17~|IFUxEJ z7Y5?11R)mQjS|SS_Ik7LQFboDDc5?rjJNFGiH|?FAEPOBpefOlrGJDx0R?C<6Zx0g8Ck-&f!qt0ts5Du%iwpobkK?1qPvAW}SO(zw zarM#|!Bl&heB|~or6gyGe)kGl{T0dX1%fZKw%8RmKcOrRNfD*MrA3qkMpLMkt%Dp5 zOo(0{yumCK<&hdaBW;otS}jrfJ8^7AS_P$ppshgw)dK0r`B_WLJXTS^=W*%aMfMb^ zPz|h27PJxvWlp?k1t=0AB?7DaWF#7!&24IjSvDP9nGv~SN2?Z6kCl}P)X!)c!JTiP z6SinVT7%44MPNg4!uk}W&vT<3IeR^nZ^9Tg$Q+%+SN#Xp_c$M55NrrX^iA)uoAs#s z3UgGzli$IRC6L0h2+BUwNMZ&-R`M0x{=FaL|6K8Bm_I(-w|$v8PnAme`ct=HWoZ%b z_`wX$8e4+~olL?$ZxwY4odA&$)8~@aI^FnqfFt*x40^kdI!r^^*}GbcxcTTF9PWyC zta?NblDyq7jS5%X1%PM)hY(S^m*%RN0`)r3ScOL)K7hA>;6HHv z9Y4hEz$8yic~gvVu+h*cUNF2yq+$!a24nM+W5v77u8o8U2LnRR9!PUoVEMDRg2m+p ztQ)G~w9z395si=#lz}6YBNCha{;6B>J?(*ku6;wve5A9R5BK?o&iC(Qb3Rt%m!BMN zcHe3nD{OP;2t?>a1XlC~(;DQf%H|4NBU%2+6;P4x5nChf@Pnbzc5u~vNO7cCz#ra! zFTQnrCX|Z$19LuuJcg1E-gf5Mc=@VH6qXmXrI1;OOcd*iG=#)9*1DPn`M$TKP)cMZ zQp^;Jc+Ix^ar4m=GB4sSYu4hqtJa`gU{{el>u5oSLwL#(TVEp@M45juhEY&pwKhXj ztSk|1wMFg`*Fysk6aJw_4uIRcDXx6zLF}Dh4yZ|=;q_Dg&~0B#dyHC{T@;E~URV+_ zA7=V<^9wTB@A&cKXx1CTQs!u0P6uQSo&+X3;guB<^(gDx5kz2kWZ239oEoTPF8(VS zf1i4vgne=h?ce8f;silLz#S<;FsLAVy2!S|LJ^B|3xZ7WAxfJDLvUN5vRR~eQ=LX| z&}J?C*|^h)e-1m!oq;do2qxF#sS{8VlVZ*>)RWb(9KOjGl{<7fimU~7IuW3zhRvY& z@Pnmm8o0#KYH(ee#Tn$PV1WJX9~M9TK7wLD%;+x*L5*K*AU{Tsp<7|I4B>t{2~TcM zib9gd;(Urfx%>*;{UbV|@F{Wu%#`1J+7$l$7uVwTH|)f6VGO60D(JN#gD(0{-5tJN zy9WV%FVp8F1A***3M#=MGMC_B+QO|z_hQ$|f-(LrSc)_Mz!%Xq8lCZAJcre**5S(6 zya7`~4dj^76P_kK-(}5_?0S{~$bv4QloZfjTEt>|25To1jFk%*u9Z+o6OZwf)8$fe4C<)nb!`%mCc{_$FzHN6_Id*L%xS+88cp|pgL-t;xxaOaGj8*pi*scomsHffLYiO3ks z9_1_(CP_?+lAHuI3uzCt?IqNU3C58qiorioo2x5zE6T_Y_nw>P2bfQl=Q(+?#wf1Ba6|C zcgEz7{BeMd!udq?a-*eYn>Hpix>t-mYn<)-mXO3Pmj8%Y#C<&mVS!sV;h6zLcuf^i zNUHe9xBnA9{jtyVIdm74J%6}~o1eZJx9&QOYad?0xkJ+^t#rhxFcl10YP@lyjg@6Y z*?p$UA2)oF>xctMXk^jD_h$Cvo`vJkxmkVTh^#r8BAMX=ST# zi%3a-BBYabxCklG0%0-7KF?kDy-s$Mk>lLU92!QnuiC&57nktv2k*n}bMs)+ojAW_?tR6zrYzXQ=CE=u4 zM4B%lY1DzrC?4B$1n+p?r*Ylw|Bd;+>Z)1wT#9id_^pX)Jg>11Q!OeT_M`<)$fQY5 zkkl^QK}iLXao5_$xZLgGcxM@{r6p__uVd@PFq(=T$k<#_uryRrdh3ZML{Bedw3#Mv z<}F<~%gvtL?<}@eGh-!K_ZXQM8X&-$t;+JDuwOD~KJdpJyCGCuT87D4d#|r$nQ`Kb zH4AQJJ=p&L-a-q%|L}b{xZKW07(_{$F5?8vLW;L-I31TwjcJP}_mb=Ob8kstO++H# zC3X}`=EPpMSm z>sm_KBk7JKdpRYH3VkF14h;_F zT!>weqFQR;`?ubSKmY&!42$zieJ+Q0d8ho7>hS!AVg0i zkTqmujgO4tk6v{J&RD$>T^cDFW@LKd`3|~RK{1!2o^(MzT62gQMq60?^q(|{Qfl>} zFKXX%4vLmyY4}aw!X&c2OvS9bQK{m_+waHUf9i8Mf6Xeq`DHIhl{Sr9_Cz?UO?>r# z?!rG`{}~*en+rCD+~WK7fydn7&5 z$eThX+wmyro5f5@YV)#GpLkP1X)Kg=TV>8p&>Ry?BCN|&%E4+;bOWy6yAMaKe?HqW z((pANrbm&i8bWTQjFe(z zxdM`M9pDg^N*yb`5U8kSX%F+g4i0qYF;vUplCd$Yk`ihgg*@8{^JueVBa{oXYp#jm zLB4fqs*7`j6=eXfM{mD!a-SNSEGU$a!yU6*bN9Z8(M6bCv*T(RQ;+JkA>R=+{ zQkqerA`7LpRK=gAT#&=fvopB-!TWKdlY%<9f3|83es}FUG`NI<2$1d?MYWtXZ5V@` zU>_usC2n#u*=!lHV*#D@Cl`gc5!oV;4*3{NXi22F832&Hn-=i>UI(we|6Uwern;xv zxoka{uln$9H>U076_iFLec8Nh6XPMw4# zLY8#g#bOD^jvT?*_?TQX-%oWvI&8j&Xaei}s_n0}Egplx0FOs40x2c5I|}=kODGqq zKDa2o|K(CyhM&}Hb-56}o$8ufj5?Q?30ts11%IxTEYrdFGxuyZ%HeWc(4W z))!-zn7VVZS34>Y?VCXO@N4jmW-M!u44u!QL>z~g{N1`4J^#*v20J4|IrLOB-oZ)b z1mpgkENBsJv#2B@pJV6K7hRh3lI}CRX7WH*7TUPt6|cj+ciofuYCR+AHGj$I7(V>8 z)9|q$?!}K!B-mIT5hgB~+RAm%=Nw3Sp4Ef^&$~aeHX32|vgVr4VQ*&z-#xw;kG440 z*Pg6wxM=KY?0C732yGLMIw=T<467})r~Ldc;T11?vAa?_prHgRxfCa6+j!mkKY_jb z4&rSueK{^Xdp$Z`cIqUea9F6;@x2Ehz`H;BX*_)BNN`~8Kt1f0=aTQ?v{D1lYmVd0 zG(jcbMOrTDtb$G(jc$T1qazsO9qO=_Z>1NW5BIqlK>i~+y|vH^4C@ZZaudN2EbHT+ z#6B7lpnp@jWEmSGUo>Ce{xz&>4Lajnx2Me*ilh?!xnRd}(pvBn8F1inc4&XHq`F@mRX84A zaLEX{zM)-e*Vnej(pr9#jux5AlGoWR2GpwU&M;Kjy%yZCn}qA2Td3h*4(-Q#c5g>Z zhDyYR*LW``sOEZj>&DY?*_vt8J4-Txnp`45lr4Z3#YUon(k`e;q9Py+614lMTPWa@ z2M*#dwr>Yh&N_fMOs>W&*R4a9cE}SES<99*h`5vCqgex)*L*{e$on9j2|u$<(2TL? z?cTX#sF?>WzTPDOF?&dYA`#C$r2_tR`-8as_&nO|stOoDwic2Pe)ooyusUz2XzJ4` zw^{;AvKFrnNU>^W1mpmalt+>dWrF!vw&T$`vjwnTt72|;P9S>r{IlPm5Is8sczhu; z8B29>VM!dm!_OQ7#OZ;2Jv9KxCvaFwC;6GSfDLTmYltAIhJh<0>GqE~0G3w-gVR^j zjUAeF5LgeZj}Nxvh5$Dht}Gz%r5l%e;w9-0IRps4TRfT$Ml0m?de7ZJ249tB;rcK& zqw;D;T(^(6M~JTbYX5#$bn*K21>Z98T0NEQ^ZU=l?|_}ZM5?y2%#stzt(Avx^}l@r zAH3@QO3Vo`yDs+0Vg;Z3xeeIVY~Y=@?LlL70*#K1&vbcCpUf9dAj@3?VbUgo`F-Ku zS;_%Fm_Ljk%^kr?V8!YQcmSX%ku#iifYh1|Td?oZ-4XZImYrS#)kNcl`#B8C!Z-aDNf(e4XxSIf$9^>_DY0vTfpfh7&Wd+;1d;WX}N}bAA1aM{pcs~z+;&n{y@m8 zm82Z7k!^zYaa>fcpiW2BZKFbky+RJ{l@)9*)UdTNjDiRp@k&^|)r>?9ti>4~ftwA` zc^am2=P{nGGZ7Kes)h!)vP`JbmP3cV^@NnGHQe9r;_B_Y@SjHyN9~-J;RtNr!)OY; zXnYKRxM?%aE;l83p<xl$9^q+FIEx6ttJbbTQ*;3OD|xE4gn) zz8@JK#mtEr$<+CK!u{0uCqthtFEwfbP`bCxjGRG%_fn@~IAyG&O$y`#=CC1l12}ph z(*uPOtVWObM^J)pYC%O^qPKRZg>tbhpT*CRIRMf^$cR#*TV)(azREnYLh8n(k16Hy zTFt8U#_GSB1C7$HxFT-EiG+&>#F{Fk|34$R<%0ymGmM9S`rpm9Km~4(!=C zU@BR{N%6ArF}(NEvv9+`dvNC*FjZ=z#J+R8DhVwDIug8s+&m3dl_@7vv&;asatR(@ zp2ck^_Tvbdh4vLcS+1LMy^fXTMU~gJK;xoIo`_DXgP;E7N70DoQ&@SkB9A})ak%pL zUW=(x2g8L9hJ@G0UOmm+1+6mfjIL7-0?vYB$8pRW8adWrLJNX?g$jZtV`%d_7S!sN zMR4xMGA?`HM{wd;8*h2Zb8-IZn^7z(%3usuSE?3^7It#A@MMeUM+`YgpphoST%(F^psAp6De{|Hzb*G3_rN* zA-wUUU&bxlcMVipwH#5&0Z$wr!z(FTw3HxSngd4+wmYdv2}?pB?2b-POepe{FJNE3 zi*3uZSe~E5&rglv((!Q&3xA^}DoY)ia>_K>iNC6VCob0_r=SfG43F-WKD5tZdoR;? zK&s9?vu?pQN;1blKcuN5zi;ZhVc3v&6^LI5$BB{#M{fKh+*b;LlY&Yr+I6r{!W$mG z7dOqE5Cp|T6t{7{W*JfxlOCQoJc4(fc^0Ncf1-m<&xopWTn{?gnW5)Tv`VxBWQ2SU z^TjgW@ZffQ{@{M$noth<^;2u`sIWSvPu#PkGBl&$T4#O=ugE5dK5-bcH6*-g~v zV($ru4+wz0-ncUX`sFHwh=M8Xxk#YsRJ}R)1L{_ng zf|2j6E$Jjaz`#b}E%x$2fSx@oiJ(i{U6w^=k#iKDWo5F+yoOB>oVoq64>pMY7#V*5 zu&{k3Vpd&M-#-pl$F90BIEk`*zfak)5qq~d3ilV@KVzgs532M=Wq^tWQ=TO2|F^vKauO=&e?;we_AQJ=9_ zuY-2}|Gt==zT`R2$L~M)nJCU2!AP|rd!*H);+=~2P!?7v!m(CIDACqu$P83X(QT!7 zn`i{9x)d6q=zSoJNmV{Net7}sX%wpXr?1|OPk!q=cqkX}2da_`0 zIUH}b@z?);Ex!3bcb{}=ePJ;<3_0NGL*sbH$S6j8DY{7)ZEIOfS6Y}r5vPxgprM_Q zqymJVe_5$9glTC^$b>v24e)L@=GpZsuADp_=NHT9aCl9-rvf*U`74Kl z0gq>Kym{>eSS%#iv9f?|3o{t47xBw$R^!}q2~{E?VC$(u+A^t-St!-;j4LAhBD&Y| zy{$D>y)!CqaKKq8764KwZP;t1)@@|DkU05gM9xeCb~}hVzBn}rzBAk>3rpNB>OSDQ zp^#RoimUhS!#f_`iA8cbLg~nDuLlJ>0(eLyf;Zu{>o=k}H;XRINhE+uX;O)x+$%-n zs}Vw%+)(N=Jshc2aM@4p#T_R&j7UoWubWtn%hs;N7~25d^x5qa+{;@i-K58cx6cUc zo3cBdt(AZp^qDBN%kJy~c3|S0@)v_7_%_iHE#&c|P7i;wZ5tk#nLi1^6m#;S+ipxL zN<_?w=g*#H0_07*naR6G_Jg^Wa%VMKGH4-8DC=_-e6uz83=o%Ci4F@{$?s*5ADh$E*Ny?dOnpZd@b4>ZDa z4-P(Z&E8&T&P;pPGk8C&^62r|KFjLj@uuo~zXv{1peaw?xC2qWJM1`Hhk}@dfjbW2 zW-C~sx+wbfSirB*Aw^*;d81hm~n`4;TkxA%XG0Wdy1jJN;s>u|xk2^1C?JXer%%&}NE zZRw)NlDYLFg=>&h)aI$EltQBF_cLqY%4XU|N{B&&;9OUMcYYBm+j(RLZ@%_ZIPlm( zyz5n$;i4@Y&`sI zis!Ui^4xeG`Cf|hN*5ceRjh9gqr&GUrN0y%i_jS8E8MCE&96*8$M%(GpK2mKPtsC? z&I2H$UxI!baM3@Z02u{+DtI(s#6N7`hW|Qp1T1>QGEd5+?_qrcyliqcUcF`$)|aX2 zPw1buemfiKPjn;D69=7Rw-GxB8hL>7!jnz(Mu$Ym=l?SI9^jUqWx4RZdfmNGZ<(1S zBtQZpAVm=n1@S+M=%I+9fPfSsG({AoA0QCAV4+JBY#=I02!xPcCz(vm%$`2G@4b3C z*Zq|D`_`HvqW^XN^KT_Hv-jF-ec$`N?^EvQe(s0b1<9cyAU}z3Uwbe9_zQoJ+m4^? z3juiDU2IKd@WL%y@x<&9GAmWoTW!@)NMx*Dt$Ul41eqm3 zxZE|0yll@U@ve(5#Zw1M=r&b3mM8_gix_axQL?3vS5Mob@V{!f989P2>$lv7!

zsv>|_PR!s18#Z8qVpY;HXZPZERk{ImBga=c`n$c}N{{{+!s@wk_a_vNz0UCSf6AZU zfoA(e;yU|WnSIr2;aD<_KY8FF{`urw2p{4HJn^ybf4xg-QIhaPT*nA{bojyr$fU#J z%I348{lB=dB)#~aZD%>Or_q$xGa#U&mI;A^5STu{i1=`BKvPN!BpTA7S5_+mxrs`X zM65~a`DguKN(a`SNC(bADa`owAu2gaS^p{+;;^mi0GM$J3u;b2{_ha+>cNbRta3Vg z!EUQT#@gcat*l1f2XFO8#c{V2t93aX8^UZyFJ$Ly25v$`@%QtGtR)kDZ@pdPFgSP+ z0)xI{l^+=Y{YYCPpegZ9;_DifN_vAIf306joLs3vg2Qb(`ZU!k;E!MPXZY?v{!8zM z76;SCP&$K8Zr_B*jg|1e+fJZb7{Ev(gRH2j+0lxL^@O-sShQBTG~y8l%-&ErgF7nA znqBpM`GLw73K*T7#Oc}D5CHI{7hH5PF1!3P2`H*7Yq<7%-^1b}rF9?t>xqwe1pe&z zUxv$%CUmBmnBMYO*G^rlimVRsAORn9;XflmW#Q}^L^60ScEy6g|VxVx4oiU<24o*tc zWqVnznVK{)s(x;)ENw}ElvIp>#cNVQ!35SyMSSka5q#?CERI{dTr7kV^}uo$_?6K? zylL~r*v)I?_-T=ijR=Cm!w67D0tu1?vq^NQ-(O6jJ5fM}%7OzWw9{RrOPoHq4u{Sz z;N5@qb$t2yyRaf9uwIWlm;iordK%ANzX|z;2I`f%jKHRTRJ{Y4m`A*bP|jV? zDV@L#YfHFqZ55-%6rMCafyWIFVpIg!>avx`(a3w<20u}4Ks?0*h-C5JOs__^R5FPh z8V&sBEq7o^5`u)30A4jdgWp*AP=zL0wz9k?bo~Id|sR~p9@7A zn6;Axn8{@%%VyhFI!(u%!Scc~#wJFk1yCV)u7r~F=)74PD3*$7HB`%=?0?}GNZnIh zl>`VR1d{E~)<6O;LN3f_kxgf$d!Q(~0Gu#Lg}}T_4x`YJkWAQ*%yz|QQ+WU~T2tTO z$%1ib6r5++(EaUw4t2*PUSDC)mU|ve540Zwhu~0S2Ot(B>UX2eI(S3KHkOSiUauku64Nm^fLZ_1sKQeHBzTa8j;;X3HfjO|^^oT#}zcYGDEzv?SETR(z#zVyY|y?H%a?J7EHisR7XrA?9* z=rC|El<=2d{}+7XYu`Yv<(hlyi=$lKExBf?KQ}ajpP!h*Xsd}lo75p9%v<89a~)QTR5FcLHi^62b=+88!dk5=C9|haP2=I^ z0*Vc`ao6SZgo?=y1_m|47B!T}Hj&S32&kh+Nr8}O`%APq>{QtK_A{cXrSVJLxtpzb zkiTb-|AccBf)5LNdFH5|sGS2D<2WR6W21qW-*+bt@;-Z13FF)+FK#B0MjO96K7c>l zeG#?^QIE>$XS`TmaD3S9=mj)=agA+hQWEIP2W!yt|Pl5f|Rqztem zl03a3K;q-qeWTl`kf~30Yf5YU9Olz$OWPlRVPs?&Yb%uhP0NrTq5`5xok&Q=zqGh) z?R{FeXAr=EfcydeT_8~Q`ct@^&{meiGAQEH7REoFHX&G+9Ebu?CYXo~4sZYCcjD_`_(o5Qon#t`u8^kQIWmFY+B}XA z?OVdhbO!5EIdn;yGUl$3=Vb96!qdSQ0)2M6s3tnNY2`F-Yc8YKo6rW1ho6;!!4V9N zjpF!`Bk07O`?d>r<6#edn3f$3V%xiS5AMG0+~wU;g`Vg*Lwa)S)*Z0Cwinc*fLv zY)fa6Wnj*1gcCZm33O{sY|Ip}V{jNHNldhmBe1b3^Qn}U+H%ceqV_1Q{i|uGkc%U3 zUM91ta-8%ggTV}r?sSpPrO`>|FpDlevVR}Gdgc_CV=dXbI}_3>cu_iuH*VXFr%g{H zM`tEBMVaHWyWHuKXh%CEqX$`z(3ZqD5rJ|RoxuV!6VpfxQ%9hL#PBd~yY()-5|2?yG%KrV$xkB#BihQ_dguW#1?k}+A@V26m&_C+k#Cxc44+|U(s+V0DBeGE}^ z31oLp9<=pgcnbT+3Rb<%1$Nv56cDXNtn3hy3A;8)?YIs~1;c7KkM|xqj8C6DhI+jE z8w)-{2aws5T(^toPEX*^c5TB5333bqk_-)$NGoT6K@Q7E95Y|e<2@%&;eXwCz;rW# zJOhB?Dg4gN3`Ru)JIXeM+Y&=$?UEy6atMgxk6$7uUFBFQIPxQ*Ptt(Fm`}6vik^Ju zKPjTQu z)e?XX3R1>D9~7^b9R?kFcnn@>Bse69r34RE^{n+V;(hN07{(u!$FoL1b_6nPaDOb3 zk=EU82th1}lUKxuc5%nh|1(CpYFo|?6ZExaF#=t|K3|@)5%ofSEgFH`8!%X6W%m?` zP1rq$&xpn8=8yzYiPfXed0%_a;Jn;WhJ6XWS|Zo2*koIZ8xydkCUq+BYESN!&~ z@Z4Yec~s|4Bb!Z#EHZij;y-j&U@#of9`Ns};TKY?wMQu=9!t}BE?7gB9&!#))Xo?p z3~8j0NwG_(h-#vax4ieGc>Ztv7ItnLlfgs$IS~MzVwXfJU&7I~Cf@&*uj1R+d|&2t zsIaf~=llLSClpraJPhE;)024Az=+OrVAjfWolZ$sKGIELN3n?ER0e4h_heuj``%?z zixvXHefkg+J)e#~2;^(NSt=f;3n9Ro*$EGh*zVZm41;tAOQ|eAd+a#=>cn9@AfwEc z_~vmToy;_Vmv7mO7i`*w5m%9ufI+qV`TqD;fduj)X!G1TCJnS&IF0@h;ouB zsKFjl3l0q;{jix%V=e*Q*jU8f)VFANu(1RD^2{_IH9UY4C#X5+Ia23dvI4(TU&drxW#LxEUCN?pxABWC7Y-5s_i>4PE7_5u9F0XlN?n}>!1nw%>-5rlEGMZeQo%Cvm(e$;d9~Y8QgDX9z?zKk zIRQ}A`*eU0g92vp%I;Sbf-Q;u8I%d;p=(k5U!rdXe*>H$i)n_@33O&8ofy(@sofDr z$Ix>cGp^@x%Apox+s!iw_4l!V$(!3s_q1=sq6E93epakQaq1UhL>v3J{#xHt^v@0~ z{Mg;b_J?uHd&nvBZg#Kdh9GuN4hO~w2XP{y9ng4i5Z=pcy`r$CgI*+a>U5CLmGQ}| zK8ugN`@=nXL;$oY4m4cE`!3#vzq@r7`!hL=Wy(mKdL*xo5xkciWC|SvK~Bd@0DI~S z_+fPsRnw60Rk8A1&z2~b2Qe}}j#I~G(P~D}H&KDdKJE#U&8h;S240JE^SJT)9|}74 zU|$z+Ux#nkSUi_d3b}=--ca49J_g-_+{MLK`7SEx~ z-!P#SI*fcSjeMbqZ~XK3aO!jw&w199(5lx27N%_^qEZ+h!Tl#sq!B=Kiv>#1p181}NNRNc#D(aaWb!}1C~GP@r)tVS}zy1wd; zhZ4YZXV&4BJGW!HlSG2gmqC@BMOQiIpc*5uNxPk8aVj$>Btv0jvksBZBAG3so6BJ} zna4Nx?#IXPy$g4(tq9@Iyo;<|ISKqfTh`-wQ(IA3Yhr$GRn-32B|rz2BKf+-BnKiW zm6PYEs({sQ2e(yMa9^{A1=`S73zwG4c=qHtwo(A9UeRYQYi%4UIy^ytTv1TbmL4Yi zIS)M|PWLzxS%R1YwCCV9!P5Y5DRhJVgECHDE1Kz~|?W;r&Ms zU@ef~^bC2hX#Ufl4n==B=c0?>-Mj&>-@E~1lxe0$0LL^ZSt?*Tpd&+mW(x)U`pviF zzLkpZA)cdd7q1?h!tYMcV5~$kh;3MlhMfH8&s0!>@YTPNE`4n`Zk#o}0e!80Zmd<- z{7O7g(DjXY2#V(D_xOM9P7}3E1|OU~j!(=UL%na9RpO)9exuu_qFzx&f7o(IRX-j~ z8aEy)4g@08pV2(uoPGOj6{O?NWwWTPRm6FVK!>0MK(UmU`2qYQiooAvJ)f^(#!eVt zlmHu4|0_zsK&3#*@NL2$0}{SJ+X89es4+l9fZPEF6Py;vdlyL2f&hJ1Ho-4!hiE!o zZ?4_f1rQ!q?7_uq+45tDYGTjRo!xmed5biH=6a})$Li$%l;vBhvK837{&{gk!dt1_ zS$Mg_v=sd6JyG-x!xu{Xt;u}X z`Sv<(vcBBGOP~KL+pjlKnu>AR9LB~cu)MT@>KbRX=~uRp$Im_Pi5M8tP8LO>xPA#7 z*t-|^?%DI8?_9_v@T%W>Hh%31k4B=lBIT`2ilwZ!mMW~`qWhQMX79G+roDvGIICLw z#FYuJ!LLtO^HP8!0hx3c87dIw^Eh*Q37`A&ck#mKKOJd8+|0gNZW$fJj}IQho3H#R z_C9d5H_t!MJ`ejVX52h?u~Bl^oJr%!Gwbk>Oaa+i9ocjj?Ib&WWZDrnWU|;@8bY~c z#McCs;;3e(Es`1lMCVP+r1V{xSdw>Z@s&jEt;JWwfjl5(z{#wfrN(Ru8RoqyGU*fe z;GzBa%G_C*#uxwMM^Y2@851M8V%x>IkPo}n)D9_$01Vv|X1)?B^~9R0oJ8(U+%oLK zGz`dT>J&>jP;cUWcioAvoH>Q6tgj!suEY#a8XLunF1QE-^DT7ODyTPPsI8eT{+{N3F->N#kGXD@?x zwS!J8fmtN*_9J`oos~sZ2eib<_o5b-BD6t}0M6q;2mf=!BwoGc0&KOp3~XoBpt&pK zp#Qbn#EX7>2P#g6Wx1OO(eNaGcilRS=CrF!%2lCrC34syZZRhw7E&C%-Jdyhb1RBo zimrk?^>`PBkzM`$v?^#QPPBg{d6I})@kP1FObXwcU&Iv$4q}7r zSe##g72Tk?u!?(Ck3-!FMhmLMI{R{`87m*es$Bud2|td>n)Z8%9w885al`7yX7jMLYQx$w;p@EU&APP;E zJX2ERl0ZN!#PWLtJ&!jlxUO;rCwp4|?0#ZS&7TX^-Nq*-v9`8~)n&FPM)!Wn!!E;? zZCiC%PnTJf1|5XaZ@%efk-vVhuZy>D!~0+RG7PjSoCV~vB_YUp0HF1KT@Qt&BQ_{6 z)d`5K`6GT1MVh=W9iV8JQ9_Ph#E*ep0Be}zkIzG z0!&R%e&~if5|;5t3UZygzqN}QaU<`5`4aTS1}@jKmV`$~%$tKaLweawv68^`;Ft!M1 ziUd|poXptV8|^OOdDrrh1vzm~?k3VAg8<`)*P3nBBt6`Z%++u^WnM8(lvDFy5Pv+$ zkp<(Ayr!*ZLR1gxEp%Jd*2v=KdJ}IwdN=OlSnnQ|d(4Kr&9aoblhoF~r;Lx{PcGPj zholNfb}Fb54IsiWSin2(pT#E*J`joL2m%1SY-9qzJF^ZGrL;)~o0$yj6Se=vwpFY! z5SL;PH*7}JPyyA?ww3Pj^ok5PG1ik)%l5sTpv^{#9*bY^bZ~d0ix=*_4@W5H9}fVe z4KS?&KDk03#X=r)bMvC~S8vn>!snNc^-YM1-@ss5x&WA=OGZS^bN=1%NP!+WFeH@} z9)KwKb-F4rMA={t{2}3wM5J6!rU&xxg`!RYq+=&hkQqL^6Zm^tdu>T~f*v;|m&qcB zE`SJ@)76WHS-2aQ`k*s>#nU+9$eokLkG5H3zCKupC?GHh*B(_bx)80hzdl~)kM@g3 zd-@uymGJ>PIV`l9SZybYE*$tbRIaWtSO5RDyLjhaJF*TX|lqD%B* zdB2zk@Un~tP7dR$+-fA`BRbl$k(0=!OL*_QKZ4JF;xkcE)>egvof`Jf9w_2X7mVX` z_s-#Xs)Vs_Ng{H2PX+*HWH{husoTcA%~jl3nG3Vy<0yys2=^R>WD-L|BeD;P0>s&} zBV*%u!LPPvxl0ygh0yK@{SIv@}(MLe^%C3D3L)I^=1d_H%~3%000j!dQ$?qLG8QURYoei9!#au~C8eD?VC>NOO5 zSTT>cUHA|@E?+{jR?)Uxg2mE}Bxt|o|3oje%q8Uk>wHl{qY5waGC7q^+CNiC)Cwhh z>&!{K>%d;zU$5%u&uo*`CSIg5)>w7I9Ow~jdqRV zKt=rB(n);a#33xnd+K?JI#$$MI1m}Enq-MBJfxVx?{C|IU!I)81ZONX>Nt~6;(0gU ziCgBD)xVg>p(kVj@WSaCOqDq*GWhKP*GDA}`@L|aLb`4Vo0ePjRq71_*)(QG;;4z5 z@)&X(98u(9B+`thQG$vykbFH{c7y_<*b0LWcGCMEE_PRVXGcVgwoefo;(cn6a?l&jsRp@iqK8g9UO27+km>fa(BP%Z@ow zX`K<`QlCweb<)EUs#QJNyf2F_kvQU5Bxw<*>X*kHax7~P4mSpCdBhggXL_HoqX_XV zIywb0j5roBN~U8_kxQ)V`^Vnfc?2;Btv}aq^zsjSLi`>>WZOX*I}H+=u5o>G9FX%texJ2y<=vRn>-eYk>TVF2Ta zY!EeJu*poBa?z_<;72Q`aet$#2tn+Ndn3oz)K!ANQ7*!laMbPC*ceWoJQ+$H{C+Z( z#$}gZj*00RYZ277lC6<2%>hh*$s4Gm#a7 zD=&jV3hFx^2uqlv>{B8i>lK};s{ z;5<=Kve}-gknoJwof6!W*sJYIA(2I>gF7?fgP0A_HZSK}PVSmsQf{{TzJhTZV< z)qHeO&zEsqeGMPD|8D%->XMSQVitNj3p{_v1$fHL4C=?1v9eafQj4~*fO0yGVoQb? zisB-LfctQ2m*a5`KGT10KI=60_A+ zJm&{@V1e@*N`aeso|{Cgg;u7751cxV4;?(zv&R!3|H0pP6LhxZtWf{I zR+HAg)#Viw%O!ETZ1W>IkjAr7=Xl;hR4bJb(Xl6=S#@P?6@vou*wz9S+PM+i-W&;cWgbZXGpU47lfCFSCvNho!t~57k+`%&#kk1#gB6ZPw^K4$1 zZ!dLV#t$&37!L;2m>T>QYTr>79dAuiXRQw-?sR>_cwW})WG&aXy&j^Uk5z~iH& zBR}GDW&{x+>sF^?WwJ#axN|@L;6<;-nG>h`suwB{v^AZ^hc{2+$f*Xt*X&@rFpPZ5 zhYm4YVdmJv@nj2Eub#miOICeuIa4TLX4@7V*>j%_t%+VhLhI=G1eO*TWuM2thR4Qm z`6C`ByahdYVYY~nVQ;?i$5>um{0Tuo0=aYouY2C}@%YOw#b5vRm+%MAeI`Z+i^lLb z1VD@~|6eM;DpAXX)j;yR45t!!(&!{EFArg$O;kds+sQzrdK;U{C0sBtgi@o8lyoR|#X*UE zlFzZO0WqG;2dzQSNwQ`DrQD6LZ1$b;`7^pX}SZkruWD=CaP&$V)gW66TS@IpEd5c%y zRzh1cfl4Zk2U=C!vbKst9iZB%VYJ=BuWZ*8jvM88zT!JZ+lHg}_PxX>-|41Mt#`0iRW(bF zc+Mo#cmPSf=foj=Z*|_Z1Jv4SJmtxWu8lX5=)V~BXsw*HBDRkek!>Y#_fl0#Q1P9> zvi~bbCh)v<>oHxV{*9q_#z*Q6iX4g1MRVJ19z*#=@eV61d8m{ z_Ve>YMaR6`K~1vwf@I|)zLS7W2jp^Dy}!{=t$%8gmpNcXYkw3Is#R(z4-_rKhm;XW z@)Nn?EFC$(DS<>3q~@a|C^W)DB}f|2V0sC(+S zTfVrV=4B5(3IKY{oc$x_K*IxzMfP#hh+2HT=8){iBZOECdLHJzqA7jH$a|$@pRHhl zZh5#Vu;{0<3TGgFv2REV*=zUpe6*vVFnW(6WK!s{p^4S8u^AA_! zEw6qv8V$|GqP#$ZfM3X^@U|@*@TGg_aJE#yhU}0SI_rKxv)jb|?JBOV&fC<#==tzd z2PY=6Vfz-`f6E{$5Wo_+X*NAAS?-E)q~USw zOlOhjpdQK+F(F8_QA7e4mqxHLmj{SSl6=fy$kf_IH$c2PgCrZHYr9NieD4r4xKt1T zE~1}2RMEE9MadII zf1oYdKd)9eDKcqLLk=f|^Gvz^zI@L}aRdeCb9sFJ_;Fk{yB}w~>D{hjI-S5D?AnD# zjSK^4*KlUFE(4I#-2}$71q>1SF>xs(4}4oGHJH#16Q_A}amUIE_P1&{-f3c`S;b|; zB|LA#dTe3WRlTO@4Tm|I^A?0vf?XxM$t64c%xr7S#Hv`6kMgxrRB&1%oe;N;u_P+S z>kyM@$(2}@;9ym=VztteAb|W3QI3@kjU4XiHt~)J?!le)n*1!#|I~PeP8)e#F@6*G zM$|c=&Nq@5jtXqtm#-Th$FI+5~vOHa;fjp;D=7J0RcRg%)h7 z_`aD8oqQ9yd|n<9KZE50mLCXVantg>$q`^_fE@wMw)ne3Y?27qAx9Gs38;a&B&)Bw z^K;nTqc_x-)qRHw{6Gtrgb=U_q|v;d*&RMN0v1?C$%bjs(Tr;=}Z0p9SQk7B8Ip3${ESDwP=9lJ0xGcC1k-aDu6k@ukLn@!w$^}nOOvSL#XmB1IA zLFg)pf>U)IzBfBET;-92WjuO#0$Y+9AqjHOK#L`!dIwvx1?(CaM3K;RlcUOYT_|zu z&WLZP$HfC_%lZOZ<^h7mA3h;35W^G+U_CsU&R{uT!WWO9#7B=E!111u)w)k9;rj>c zHsfU*H)4!aDmzVd$V@lMV3rlsSUV+E`x|}awiI!sx})bv+BSLl0+pvw&E)Z&<$1jC z$bGnn^2xEU(G>6-n>OON$7WDjuHlGqtEfMe$4st>Y^^DQl%gH#KsYE#wF~%BDVg4Q zy4k|MZWVW|uHbZa4db0Ap1FBFetu#MB>*7LT;_c+IN=)dFZn!v)UM;bv-jhE z1~XFX>7f;wsrTS9ekZ<9?bBU+%j_^MeF;gtX=nt$Iyr->(K5OuwZ;$zzMB)))uk9d z5)jd7jr@Mp(ud6&p~}|7FF}AO{!tF+n>mI)M@Y5biI=Jwy;b)9(@CQ%NWsA1fVBRp8lMj2VJ5U>^W_WXUB;WLu-EQuut{*Li#Rbfz~KW05mK?HOib(tBBD&yZGE{isaQixM@ z5~BQEm$jz^5YkC=`i2IGBQ)4W{%YFw?!$R#D2Hms{|h!+dFCuwOKj3)rerImmTHQ=f0<3NpxuaHD2*>NKdj)wnAC@ z9*@2ejdAp^E#;X0x?-Ppp36dG#@yx}!(#&!R8P2VLd3P5=BrR&DAqn5#~^J^%M z3?R`-AwlDn>f-wPBJOLfodf@~mcQ+x4@GHs2y18OaNw@HdTRZ$KFOqL=(C-b}>G?Bo1+pV`^NeFfQm#%y4Sx0p3Ns3cB)06>iHWI=SYgLbv4CtYC#48&$IapNvBTJN z!;ks~GC656JmsjQX5Z2g!Dh*f1T~pT;>p8fxV%u7F{{jA6P((HB#PY*c8(5VQ>uVG zRUoO?Z#wRT&(#9=;5eFz`9Am36U!%V+wH6hq9D?+ic0XuBy3i*d3s= z6}tt{KM4i@`pgvmc;j|#;QPw>VU?oRa)SnM8VKl_;yqDIKx)xa641}q*xJ5lQz2{V z6n<2%;hhiMhnv}b5WBsh4Dh^lTkwqO8LTZ-uvBSaB>_y7N|;DykgxMzSUS~rr@n$- zi=quWB0C9&e@AK!++C~S?)oauHmi8VSQ)=PIgLw7oZV2DQjeHaX@TT56AcK9Xxxj4 zs2Vb0B67B#0eN)CA45;T!(u5{kNpbYPhdEa!dr&N@YIP(OpR**p!Q370J7rJ zr4rjOF_Rko#H^k`c2Vbx{M`Zyx6;~TXy?+7O(>4UOu2IaqHDMM7u7Lkk9APZ=5W=a zqxit=QRzexd-w4le4|^)W`!lni|5)iyA~Y)PU90oUK80YIgnj}@Yx1ft7x5{fdGR8 zX6vfkpA{n|5vTNfQ`%Q2{_*>bMja)A^cl^ykfr`O)d$l$Cb&_p3ENsm3s)3fU;sf! zPGvH76^QY(-c{!V_!K?Of}(aaf84T&R;vzKgJJKwz~(4JP@pwsAH^C<06x(wK<`l( zfo38xEI&Mr2)@zFhyoaYiC;tb6_pB;|LGt4mwvcDScj0Y$L=F+9eWRJ5fs>37o>*< z*IW6IxZKgE>SLhVGj_xy99YjrLs6g?L6K#W%rzDvtNgl@GcxG{jvPFN*S_)!?7QQ> z-ZFsTcO8^d3A}809GS%~PNh0%X0j->6C(fnAGJlywtL61@-wrgGIm^knTXPm34Y+t zJFq-A*XOCJPr&_3p{xD?Ku;XY1Q%X>F$M>Rf>@2hp1{)5GVZwb7CAHL`&vIefj@c4 zi!i(QKK#a$9xsG6af(vL5EH7;#cFvhPmTRTpC1i>`-#Y7q zEx3&N?)uU9v3T;N_CZUA+3SQOlNEJ0=rN0R352uK79+Jgm&MPIjbnGJgd!)~aYb@T zG&(J8&J}R!$OH~#M>lbQgyG}MyA_B ziq+#FO>t%@0nN~yg z%ch}03{*NYpCQp{$sTbsq#}6c#Q8>oJfyIcOk!`RiCdb>IJh*2k!};u-nw3x7oSzwylEct$~=pJqp!b%)w{5L+G#M(pf|z{bv#Jhe~`iP#Go^hTIT zFVbq>L@tX&RV6dFa#?(Lei^Ucw-*bh2ax#4)nDyW6I>MhIPgHG{VnQLzidXz0EGMJ z&d!VDrlaQfq_$5@et~~=8L1w~K|V59K&A?IrIzoGoDN=UmHe5>m$F2_0D-N43=o** zc!EGS_z29hST_|kfgA*LLh7h>K_n;$3#5yoKkm)SBWD}2+vWO#V~V0% zB^UaZuuT&y3q-D2H$e1icm5tZTSdG_U?&O#;-6rTFOUPGAjS?@xTjdRLaYYrfrh?& ztSdq-aqMoQK*PTuH|Ozd3Z(`sb3~;Py<<6EvE}TEX=9}nH`MxCtI-LqO5Z1!AHa`) zcr#w}lGkGS>_U92>)+E|Y)B;WoS|`~7Fsx-V(mMNg+vEe*B7yP9tT{Sn84OcFOm0W z?{s}>5%=DFt3dd@UmOmUmjFN{vCs2W8W_Z`UAr+fIxPFv1+2K|XOAAn{=Mff1<-lE z@x{M~QnQYyTz07h*up80y{WBdegK$lNuZk`N@ioPnZ>2pLPwXOaIZhJM52Y#-~itG z<*#COv4+3=i&t?*Fy^aWyyW%o!hhU+`+4uhze$qc&I>QZz~C_Eg#Y&b%;)j$*?sup+(~hK{-r^{Mm%M53azCEPF0#H4;8VkkVkj1 zA+rJ)OlWtA0B1&j(?FY=_v8-zgWsI*r zZv|LrGn`ArJ`4s}olG9LH>-I6iG8@WR@J70cz!Ln;AwE=JK~qy9{_AjXYjVcG5pNP z7{AI&_m)2af*@#P zK1xd6R|8&r-yZBSj#J`O*MGCi`V$>04W2XV>5yfZ52y5H2;D2=m2f{DI-5&(%15b75ZpF~mu2Rd_ppXCBNay~%m{U=edO8HQ#cBwdp zO#Y*hWC=iENSl^xgg-aFVLo$gRpQ8iw759bZ(d5rCtB>_1VVd8L1(}=iY3kJqQYlH zjx>U^&Dex&-?yGUq@LgRP}#}}e$d1i*yvcQxsb|auQvG2lajpx*itbSa$CQ!H+cGgRO<1>Md(dggr&2h4 z?|nFPZ1x=QmC7j6#Mv0+ISQ)*lcT44vltvB6@TD4ziPT%RtkNa6X z{qjrj@aZXxjZdLPQ5`BIO5n)Mjngip=a$JOkj=3?#y;hiK>DH`)9Run=`OSK6w>Sg z%N6mm4}KCm#wPHNH@z73Tm~s|#l%(W3ME{@8AcS<+zJC zDdZ|-;5R|Vyk=Wb7pcCOs;AomZ*S9}%d_oBpC#BasYK}ccU!|}AcNf;A@yzu21ng4 zR#s|)vPfqF%Vb8xrK%;{ViV-6(?>N_E*Y5|?nMh9IlE3p{;eGU z$pzU0-aa&nO9w|VHa3V(hY7HRk}>-i`oHwP{0;g%wI{hDEHQ(vzY`xZulRunu+qce zzw9VN2tHzbw$Kjg$e{*;%iS!lIJgi0aO#YeqV_$(z8zp!mt~a5hj^W zy9UI`XVYN&d?S&I37a;>_K@B ztD8Wl3!XP3^uWV~Z9MY`S+Qr-y-&S&n|b~dhs$(3=uhI!D{&(V&+- zJcuz31Ifm$-6lGPc1<3B#>ygkNp3)GRYF$fs}%33i1-G+{*DVqv8jiwnu+MSry*9g zJ^s6t9mJo%`Q7;P-~OGhO$f$}shjHJk?B01kS$}i+Qj~36W2AWsGlcbn%sT?#y4(| zte$&_0ckdoz->Rc9<5rhLYAIGh1VbKE1k(;dS)FqZ`~TYVt5b7XOCn5-uuq`t86uV z$4h??+p-;O+BA)3oppBV6J$`#0l6GWwN9AST@!*WAw-FfK&#n7tq#;G{5SjE+US%A z@T^z96Hj~eC3xfOUWEVk>CfZcANwkr@jm~)t11i*V8`y=7#W?w*@by5%r9el-8#`l zAa6nx3KL0W@@X8o|9%{}`wqRHVBjBYg;&H4V~QF^0Y6Vn|5vV2((J;h58r>{!pK0s*R|D1WyJ zfNVqLHPXq~$_0FL;ViB^cnF6`{)-<00Gp^4uyYrlJ~)i@8f(LhZz}w!_Tw(;&YO4MoKSTWcZmvTI?W^&f-wAjlVp31m9U+5bi@5K4i8wLW+LEJ~n?r zA**+dj^V;`8KYwZqPw9a;CQg(UcWc{cb^?Rj$MSCP(S0kB9=_JJ?yc=rWN8kGh!R8 z>>a8P+IH%;l1QQOjJUbeMSSe!3B3E@0Y#kH1&~Xpg##d@KKA-I8Y1)~Qi2rSNu@+2 zh<}n8MRK1^4rI#{-!q*?Cd1!lOJ7x{|M4r8NeMY)ZEa100%q@=wa(9x@jaie*V5Oc6SulLryDCBcLXhz*@`@Nel3Kn{y`gjHvwwfZl^wR(U zAOJ~3K~(V;1YXmtRY1T>6uQamXEEp?DpUA9#;(COeW+RWoehZ*;w?SSt8^WP7^yNk z5;3U3VhQ_XTjS`P>R;%nvuLcf@!D6C6nJep-u@x#E{$iSjHS`I9;9_pxtQWbTflr zeZl+jir;@Gwr?K7Z@%KsF<I2GP@q%K zB#>&h@W@S**ibB@wNll!BGJpogUi0x_GKmJJMB(67k(}jZ#7s^GGui!0&g=|q>W2< z&?yvfORa|Y9@vlTD>_U_KEnQFzdk4Wy?AUr3bhKFLiblfqD(53AfqLL0JB%NJ&JUa z&7=3{?k!#d&vX2+W$W!?9^YA7!rNx|;V?;h9s~e*=JX_fZSxi^&DW5rHn6o=M2@P1 z;$S6J4;eqp3_>)O{EV%NZ9yRdHqoKx0?D zz2%Kf97uyyA0;ddeG3G{Nt!KE-xk&X$!qa}R(v-fSSa>NB?d1ZBp;AaD1>VMADu5g;-T0z(4Tiy!#91Pc@hf^p9pM-JkfIyPQ5 z+<#O?h)i0%^k6FyBBkic!?)r=K@VCGtwCs+>_;SG@P(_%`E2VCb;Z-tzk2!+SsSar|)a5i1X!>-@>?-*w5w7#yavPvPk7 zQ6c_q*t7*4T%#pBgL@Oe?Kj?lWc@wY@}PqU#o&qyf+H9 zT$(B1S4$(z3r@N83$+IK%cO7Ny;gp;$`G-!8!vo1AK5*~={&DH7WR&q0V5{D1Hf+WVre;u}X1&1qe7aw}+=H9fq7H#vlI4JDJblw9q>oiltaY%i zTo4&(DKCg!>ETdQHQUcp2ugY~5%CW?7vr7KG# zK}BQ9Ptidv45j6M4Xu?}&ek9hswKeEKuiD+mO^CjE6h(W#ag|ITD>JDFZc4Y9io34 zCeY_K-EVlSb}E6DYzF_nwv5l7cmM~uPkOel+BXXed){4qW4DW+Etc_?kqKM*E-q;NXUfFpKN?)_Je~1(vwd{C*^-npFAV2e|&JvY-Bp% z@`}{(nep>ABs0y=FJNGxEJQu&(U*+9gev>LZ5I1R*Z!BXeIQTJ()yjJQ?0DYxHxqHeT_;uVY|j41fLke>BH(u9Hq>v$){G-58&ml5<+A z)^PaHEXF6MF*Gu4S{5n*!}~dK-@Q0?aBncS>Q;M$(g$Csz72Vj4 zTkfbnO#vneK-yN8B4nS;U@o7=CyzdWzddylZ2I&dgMXvG!3)++M%$XDgklcCp>PSQtPHO2sWp2Ugl2jXi9{OrW?K03Bm41#TC_ejTS}=S#hk|#z&nEo58{9cjj#LNqRrOi{NP4!p|^KS;|S*J8e|!b&L+= zFp$flT*#2Mpm4jA0!(hnCNY}l*3VKTMs2aBR1)LpL+7*SJreR~^^5MadSaj#B1lwwN73O6FYc+MYNWILmTN&GnJ&^lP;e z>86S{UvS{D;4@eRuT{l?11rDiTeypGMyr=P{E#_P6GhQs|4TIM?!~nRlE|lvxb8o$ z$DdyDR-8H+7x9S}Y%G&P1xZx7r~1CeHgCc7mW^gG^?kYjGRc&%+q;bhZock^XgB^d zk(>v2bwABdi~BLb@v%%;;gcH|)Lzw1tE zlk@%Y)8+mBPCt%L#W!~J;=u0nObs5wYrm>JsWMidKJ~+Ib_o%% z$G%W37$nmb(jT*Yu2`{9l(ImfSQJ=(VSW)qLjyV+fP;W?L;@8gtx^>O ztFpcw5m(_C0|Q=^hya;$;!W{&gn$@iup@vDp1(s9AyEL9BZv;LOu^Ta45=DIbYyW|_|M_2FVPUZk#gR-YSB_!CT({s4{$2WzRsh`G~|94))^YONqKO1j&?h}w` zRZR%Up+n2ZY%N1ICFaaEYajxU5ho#Vb|#7WMgqU_`cLEP8}Iswmo+*$i5(YSAWEFs zTtQlVXOEu3%%;s&<|CgcAt>F#=~KA-wwuunZIwTr>;KQ!ByOT(hS$$cc4&$`b<=u0P@YI--n-d^pPR$UttfJ3AGX0o?l@rc;Ht1MqcSL!u610nh)(du-u+GwFtWBV;Hh+HsUb0nqgkG^Mr zdGzAjNd8m=LpYQ{5Y9*neD(r2Wbr__3Ai}wKHN%;Z1 zVRRZ(=?o@E%1C91)^MtAuRT{0Do+G^?YTR3^Hdfo`5sq9nin1HynBARakFoBe*w5~ zv8&)qdTnfADA@UFWK#GbC8rM@V*v2?UFp3}r9|b=AwOo_LcGhQu{ggZx&V@Gw>uab z9+ZB6GWcDupU#_bKhXhl1eom;nx``_7W2}+#0;NV{HkaLC{a+60?KMAQoz3p`(DU@ zO(_BRpdcD-cf4W<%(3S(8Bt}Eer#$iO9ZNjg=}yl3${r1Q#C2UTl(U<8eM;FGe$WH zYwK~I!B@sE_6*H}*1l-f1CIDpjiOccmG%KW+!BqT`@iBQ)PF79Q{RgNiP7wLFO8||48%uR?g~s|2XPlC`$-v>@%Y0#6Ea66hcNzWKhVK@rA$o zJG|@9-y?hEoOL_A^ zEA%FR<*^UNm)`qwl&~gaV#RC)f>g9-zLrL@4q2x2)^z$CkjNyl@6;Ne_KFYV@bUgK ziC%0bpTR{By%dFV8JQF_!vyy3*^gpr7^6a9Oh~YuO{K81G><*E-->39?To#9_P>4W z5BiI-9UVR{!vr=CmCz;{P}Nc5F4z>6 zz!d#d`>LvOO4>6wN2f0aIco2cWYyLDNIFcUa5$aDdk*c#zb((9Awjd=00Wd~3=QIq zn=Zgcit;vV!mpt7l)Aoj9N6c_vNjE33G@xrXD7si`lTyXI?Ma_2L-tYqX4vvV#tr9Zhr`6VNI zn=Mo-6$}jMfFC|k{++r2kpduf`WXzct3YLf>s2N7F(7cbo^X)2^T~!5ooQVT5ekxN zNnL9pOo)S*mO*eJ78L>0LgHd$2!jxrV@(FAwbHPBpfjkIt*`4A)yPBD&b*yJ2!#Y~ z5%r{m))oycEG00c!Ic6%Id&(m&|%NxwJXq#tTn)>RqlLtF(3}-x;W2?%s})za6c}6 zSePCBSlK8xNXP;ji(JI%+w}*cmoc;BsKU8BFt&E*xv6kv2E{s=GT@BHFQu!>Vw{FA8P`qcBs1bw>8_N|;oe(r z$MOF}HShne6Wlg6ihus}o3U$@$e9iW664{{$8cB8V59qY=vvJTC%|zECXgtU@#TNN z6VH3oC;G@t(Uq>-vJM+JZ{v+i>+X>Uj$&!PikS_YkYdYiDvfL=g|($Q+;`WVXjVBC z>HiDo-@lsCXNIzrzE3|(2zuiD<)Et_ux=I^{wfF{YvJrhS8||avHbj01}F0ceCX&teC^aJ=&)(s zu|xu%Hc-ZEwqAq_`2Mw;Br2i_;L)9^0lMSRV1vX#-n%H0+URWR1hf-c7pKUhj7;xR zFert0&K|};F3zE5Dw~B=0?*yF5&xqwiR@ZM>eUp$@?gf{eRs6M|Hu)J+Y~L2h&p8m zQuOY`{+W%WTyI+>3p>bXQz#d6GNCY=(coQMY8Am@yi4MDl^H*!eaUAL!lR994#p-WY$TD>mNJ^S|w(Q_zJr9xBkh2>Y!Db?J0Z6^jh_&w z7=$#M5ZdIV{Ce>#3TeQzyfK*2zvhm;pXl-;3)Y&et`H84;f zoi4sd-y!qvYh&@l65cD0CfI{egVEc&9?#IdAJ$U=`zb0+=FvYl3nDwz(X^6JauRcTN6nXDs60<9LCJp04nn<=r%i2-ryE9Hy_SV z*l&KGEEv!LOrdDqt2S(h+#~C`rbAyTmGPAm$MBis2XI0)i7W^Jer}+EH*UKK59wym zX-Y@B@}&%&Oj>)Mq#((zhy|;TfAraM0z~*ogI4_?)%lV*Q%vDQ2lwGCOAFGXNM|#i zN#Nz1cH)V-0VI|g0BN@h--7{%?kRU2zPsF@M8T2R7k{n&*h{Vf_(DY~(QTqdId4alZEpyF%y?4dOK85Q zgT5V4QuV{gZb#^!K9k;%-xtCD?8*53>BLBe!LG*xD&^*JV(9IiF0Qy`KN26i_G?|j zeSAMrzv4`2A?5LqWF#n9m|Ku?0581J&_I9)04Ia#@1z87&lj>N91TWg~@%~@O08X2uP<5=Eay%@|V*Fb-bvK0@lf6>aZAyxbOs@ooe;dV5?-Xj#eeC zrW?+O)kI`CkBoE?<@-js3cc6XJrFjO_wmQ9Upy*{2NRwtMVYfc+)yjGO=-!mdF?2_ zlGoX$4CsLU&N*0uUr!+J#Z9HZbzss(KU516h{$UB{Kx+KK14yIi)cw=d(c)g+@r=X zR$loD9wUBm{q<^yHJb6LSszjiB@xYhg%tT8?uS;TgDcj-};QZ5{kS@b%^w{4(D0if5u#U6$ya4@NV; zNNP3gRX2#1Nr_t!#yBSccCp$i;ul|hC2qNQ|9P*pI8egwOD+=PA7y_ZI6RAbwTY3j zNjd9uii>AYN!mD{P%4}e6|>PcRU^nrR%o*tjBKevL+sF)EUpmgB+E*noh#yd zEA#l^?0($Kghq~=HYNV-KoM`>b}@E$(h>yl>V=PQ-Ax=RENy|Jbmv2SB1qZU@-|Cb zuSAFkBnPB0pUvXR<45tev&RL6V6mO3$m_T5!Xw&QBpRHrqKd3CLC;VOM?IYN?5JPp zjxdfu0JP6Zcr*}kR7!XjJTq+JHs2Bjug*m<*1R=EsLq83SNd8j;y;L||H(g!8K3hd zXWofnt%<%7DbU2vJ&iWrdE^27ut8-in2x$nr1UPLRL<(=d z}aET1b7&*qPzW`~kxJ&iW4lg=#zV^9z(lBhXTB3T#G)&+pU8lOI5?f=5oO z8=$bi%&!hgWkx!&BvLbN&v-4eb?DojS8#f95r?Q2rHibgfbK6##ZCR|!8fLvt@Ak5 z$f4TV3|YPJD(%beard!nj`oB{4&GuD4~cs-a?QZ|LyVYh4nc<1n!Q!E_a#=2uvj5R zn2cL_U8<<?a%!h zotnh<9XpUO=7nhWz@b@`ie(hagYx2qvnO%t*iq>n|Nrxsqaq&8%Uj3=QJqMjE^FMO->Dg1mGSwb*)ca;c$(Vpa*5P5Vkw=cbPC~kq|dGO8^WO7$ERH7!|VwAc}&iH0m;+KotNP zJ*kwWE~3;ogh0Z~zlF3sB!$=brK-2_$$bXDSUT^A%MYnO6nCPbz!FM!zOkZB7qt{c zKl9YuVA|Mwy6=zNZZEbKQAhmn==I0`73<~KPt-e(t~vhNh(H#9pQs;K-yu4Varj<; z6r%|{Jlc0e<8XC+edO9qe?5K&p$y?y9S%bOZ%6m%ftJIIJa7_N)`2VE^HF^6Gham4 zd!l|yFP6$>uyN~lOs!vsOgWEop@3amHeu7`1cnC(kw|5Q8_;eiMZ`*m1hv>MTgSrL zIo!K<4}N^ptvEKTGX>(I)_-;h+a`zc@1MQ`TPI60cfbh!!jh(Ah_V7c18+1l^D1^! zGuA{gk1u@tF1+xqe~H$4Iv{u*<1;hZvTdu3_C0m_4CYQRVsvy&*w+hlC$Tce*2-S= z=Rdpt|Jy(JJvTEtgoj^zIllA5Yb79xzVw7rH-C3Fhs|Jb6p;V`AOJ~3K~#wh9+Jr7 z@zax-$>xwEiB!~1HJIw^!t2DlBn^Ko;PP@yj0>Z&tf`iYUmzl?6aL5xIGjx2Lnn^l zJ9B4Hm8Innr#2pu&*KeScH?I=1+?o`lRws;b(L{d-F`-uz4qDmI-w$=R{FAee4k(F>*HXb?kM!@iS?!a$^|# zr@m9nG09)!!9^4p#m~<9KI{B@?WcdG-)H=D+_pLTs2EZg$C7QlefB7BuB#8EJ9$B2 z49^=LN0y0dw}WCXg>^$k1@_%RJ3eJqS|4)c`ZdA7cqu3Rp3bfaU$KBOJn5J_3bB-N z&D_3+QiKONf|@E(R#682(ZX7;h)>^r9Enf==v!S9LnsC85VXMbt(MdS*^alov?9)* znL6K01b3{ZgxR=H{9|_jKY{IoEFE}TAocuJp3_*MB1=tHD!HO0gS1SnN8x)3SVRY! zv(EJp@c-!O`97{<#lI_S+2*6O&zAKXiF8Pe(&$QFC+FLGE_;Z58ntOX%Ne1ja>C^p|4isP{A7sA$w+ zujQ*1)*%wGx>UoTT=6zs^X>2bm;Dm6@1gNgT>3MQ#LjKov1{8#R2G+U{P+pX&&}c3 zu@jhESi=1BlC-|Eiy%|TVQg#^+cs~<_Dx$+ugu}P>u<#U_Ys1RT6=!-#UxP3Wbn23 z{~@0GGuzRruW2Unzp48VFiWbc3m9Hib#v%AJvqS)8Ob;jBuAAfB7z{IVgeHqBqQM^ zi)0uKARv;X1OY)MD2OPC#9zLEcb{(ubtdOF*2^A$hCUH3eI-#z}wn6oge3@Hzo8i`?j$HlIk?AG3a zo`!>%9kpjU-tK6gk#mc2KMjj#!21lA(b!55GuKUei<}~UVSh+A|t^Ir0@B3Rn z^aO(7MV-Izh*}QdA3yBq*1DelivXbISR%L>oRTTW=%fC~VF2(E{#hzY0KnN?-%R!3 z3mx4$Yry5RtzmLDi7XWt*)$krk4ELsh}D^4Q@VkTBes8$Wu=o^aFfwB9SnxDVR2^}mn6zFOw%cK6WIB5A_M890o3Fiw(#YCHg)Tb&V4U`?&!LtZ zGSAcGVjq6@a8)UR%J&icp~N?5#ji4b=y z`2xUcg#Vv?=^|!F!`)Y2f!Xa5JoMCGaP_?pVa4d+xL3tbv_%|rI3707X0T6NH@5N; zXsfYzpR90-k{J@0K;0 zNPzu~qY<3D-bUCV)`nVyp~|2$v)aA8Om##AMTpYXxt+y`@x#Qa3<~o@7Jq1f5}I9tIY9JK+FYx znCig+9o?oKS;8`;qAt2KDR@p@OE!{mYdJ^0)y#{r2!Iei#j!WzrQsmTw=sS|VSf@T zM;l!Qdk<_ZmM) z?Bid4)MebL3HqBIopGi%1GV$SeW3|mXr{#NM|9$An^RkHz?Nv^2f`s|?|*M7GY>Cu zan#{eGv53B1!Oi{NI|N#L!sFfhqjjQ$So$NziTRwXv`G6LdGM^Wo^oAP57g6kE$fv z)3x0W!2xag!2}Lws+wP?G;OjRRa>igIO#hl;rS;y{`UX+($-SeiMghDg2{LsQ>OM{ z=G5t!HhB`-(h0OB<48wby#LOJSk^a;)TAl+#1>nkR2#+PPyZQj{`2)Up2!hfTv&2BIM!H>X=hL;R;yp~>S;sf&0a^M^9YrUCSIPxk zzW6=-hi%llk+4bB!5K3*#4hm;G)j3{bGEH4=#(*ab1Uhpk%d9RRCZ7KPZp`v^pR&X z5ce>D#fSJ!e=iEIgD%g(*Qd2yG!wEz<#c0~@{$EUWWVK7e z2J>&vQ(nWaB1OQ1F zI4wO9d$sG3ED@fgHc6v~_GAoQZ7ExWHT8S7YeWhyq8&*4sZ|Whyk<|2lQdZ$(RxFD z`)w0D!Qc#A1^DC(}vM=%)kDv}MuX z+b@#8s_(DEf~X2eG6|;xc6N4Rpsyd9Y+7oPgM)*}X0wt-kt~?WWPAzVbSjBri5db8 zK^u6JhzjsTt(Jf#>FIzWog+Ymfx(CLiwa_4vUdaVGeF>lv7--`URTt9c>V`>b|x!1zKXa7ARdmuKxse^w4L&*=H2w*-sn~0h4+h^L znTwo|K@-gR7?)@5Z1Au|WlROV`R&z;hx1Om2#-JTlt|b9?_Y*j(x@SwiecXNTVju$ zcEl&Q*c2OXFcT??WHE@X)lje0WF&1PUq!KZ5W_2avGn7GNVLUKXz#*ZPyGqMd*lx& zg);5%s`*G*sHA*yQI1>I}(8_36SW>>5v=Q^G4QIdg9fyumz8+j}&B2 z_!kTwJX9%yLni@8^h$V~iW|WjjXJJc_#gZ&PlmaE|K^bhPMfnac8sQgg3d${;MV#{ z$>?pTjOk1;J?tVxL%V1Mi)tdi!zq6z2&gsCpNitjFRuO@bkbko3HgDa^I?%x7f1cc*h)f-L83Q z>NVP~1B1p|U4*Iw{HsyM`O7}WM^f$sQZ8_A#}w?C>5%8n5*?UCWk8m%SxPeH z8ryAUQ2-0^i^P7H^}EeSpv0rNE%ax8wjm!H+zm^YW$HKL4SqA zfc|oSLxxO<@vI8TZ+Lh_3>-rT>ix6rj}U?o{?aK41bCIwmS-e>NzRiYKM~~(kod>! zp4vbE!u!}@52MWIK-%49hv5NRwK9>Hx-K81&0coD40*4x#ROm>Z4aN3++%Hq|7GECunJq-~Ef$EF+7j`t2D zcGf;w2(lUS^v&1U=h))#eR~?7`(S=(7DlTdU*`Z|9Tt&AD+EWOV>E&}9E1E?t%&oM zFUB$wa~WW|z(t+Yuw5o=5*XJ2o~upegh>2z9VhwIQFh4ec++eGe{PB@uNNhZV36Ut}(p2uLuWSs~D10IW! zHIWDH@75fJ$F>s!MIp^xkVI0F8S3I^z#*Iik`s-Sl-4O~7{oj|A0%-5sbkz_g$ki15+EDBIVBJ7EXIgg80;{h&n0Uc-0NK@v2)@74pA+1sCwS{rAEd zr+gRFdfHJa4xvIgkVGrahG+X}Gzq8fBElN)NCCquhT!J8!4il^l4y^`v1-+S;AUe$ zEQ>oI{R3`!_)!#EAnAzXVE*Yxv z@8|%Q_4lK%a@?vB#&JY7ngNS!=~|+qPZrS^hKJ`KsFUe z2Rq=*up)&?4w?@RKBf;W+@_7?1gw3TN9fzUeVDYGdQ3oP#6*)))(aX3_4TzdP zG5(?S49r^fIcd$YM(8Y?&mmkNXbxWVI)nc9pnujHdwUJC1&lsGz<@U`Gxj{p&gXk0 zkvPsd^{06Fjz`zcw}szj0**-3!MDC~48D2Hmyn2(Yf=^nSDmtpDD@~Bb>v0)vJQvN zq)wuMgJSOpO2b9uhI9Dv^>;8S6~#td%)w}W1ktV@{Q8lnF#n;4MCC2~`oR&q;*uX9 zgW6!9%;nHQKdz2S4XKBzAQ7`W)m}$Dj_3dJArAP#^(dNP`Md>RA6|Wt2o*;b=gMLbQJ1+9&3RVpCwrqc z!84UnT)ccKMyl-c2PSfW&V(758%vn!LV9M>f^PI1*m>5TN}?m1lGaj5{A4qz4Ysb@ zZ}&4d!M_(4Rq}%qVa)6N#ik{k1CE+uDQ~&5NLu?`Q2lot7KHY@K6-r53_=K{HUO zR45AkFM0yzc+xgwpm;{7?DOY$F+iX*XL-O60>p9GCAc8uPg0?j5jb1G)LeKYh%gY9 z;P+-SY13D!3s7py#^=%b$wLdXYJEo&3JuLe6KBK?Zli5i>pXTt1P?Ie0Bz5IXdeWQ zxjEtuYWDhh{fMQB=x^tD=468pIUno9bnL3Y_2wnWj14kE3p%(H#(^my4)ZD{!I?s`)Y&J^xRPe(*M?PU=R-ob^$vMRDbC@5cRq`HPN!HDUd{ zjb`HaH=mBQTa4*i{@%)JP1JmX~SvDsWL z%a~xD-%p#y`^bN3SK?j@{lz@)_`|cf_xa~AC^hirm);YW)#^w#fX(9xe5P|EcFA<0 zhe05Rz|ek)ffp>sXYMl?;B^pE7C_w?c4qCqwgc~z1PTq5;&D7S+K20wEX2~Xsu*q) zjp5AM8{iXOLdH~!9=%CUR25qdzBThcS|-;W1OjRjv=ku70b|t$kWWW(Tkj&=wThZ| z4i4#>fUosTLo~+`%4|DSBtW|g%(pZdx*#}EGTnHua35Q901&b!tGV~q2Cm_`H~ngL z$6xKq1rFKRP0i+ke8k1W`62v#_Wko`gsh}Zkm`U|w}1nP zqOORlFkq3=gK!mUDh+Hp0&D;fc51e+7k&WN{nGh!45!>rYH#|z!Nye?f2*8=(9f*% z3q^PGTc33sxVmtBZP!G=6|fKAIMeWEY|7q))ubf=qa5hhEj7FI<9EXz^`(%FQ3-FG zG0>8ULiI9&erVfmYLBls%Ur90qqP0WUzI+r6%K3y6eSdP*jOgqJzNXP<(N=B$rubrchNdXR4KK{P>f zYfOk;_T25>5cN6HtN=y|dGxL7MSp)k%9Vobp|lsps=vRAS04BacHe(TBx6yaJ%jID za3x-R>m5I+>dM6N^tGpAvkiMtE3vd?91Hh_=b(Sp5aRJDGFeXLR4eW@YAD9r@RieU z!~=hN^M4ia*tIAd)MR|KrcT8HyY7uWw%Qimu^5I%hLO(=BT=i$w8VHeEgA^43qmI=I zSU*4cN7!$hO;8wN0H9g6K=0;oME}HoaSgIg>qha$f(5wc!H4nk+wV|TVKpyD1cBNd zU|w4r4sM?;(0Q5z%!mjWA|Me4nWk!ln1sJ+iFLxhHo>?@DIjtMbWwY?2CA_b{!$sm zRUdtT|5PgkQ?Nxcjvr2+i54Kthw@tUof4FY{y&2N-Lut% ziw9ON#xDnZQFUA#K6x@e-`0cFa1~{?6q?p*pCD`>ix{tUd^T%&TdR9EZq$Dct9Re# zEv?57eIWQ__$c-R_Gh|YC0pmcs@IW=dAM_=AM<;c!zzGpnuz0nCeFlUk0Xjr<{e68 z1aLKGjU$3t4(K8hz&&MD{ltHnuT@Q&aF0~8;%rmyBEH3s2K@CbBa=Lx3?SE zi#_}@_)(PtG@1S5O6N5@>58kp#XpFyV%FL~)RhHa9XV7fB^UVv*8PW0=)S7E^%^jjDpxL&Bik zV&8#VNJX8fW!P%{M|l9s2MFA@5A(|^woyQ6ue3OQ-_8lbVC|l60UM0yDVhgB#0ol_{7@B9;7KvvWPKx=cUgwUK|o7Cf%)La~U- z=pb^#1ERH`EalMu?jpF2GMs7!8+>9Dy#B#reE-7Bv8caa`?%|M+;q~>`07!+qC7Mx z&tJ+k(rVPek_Ag;A55IlfqK;hvTg$(4L7j&v6o=s%KkN8-?+cj1@Eub4W`e+fqU(P zowwQok!l^4fnh{gs>`O))|uAvr_}2ZWUz>Gsfy9j94h%dqLl{R8U>kRQb*2aQpl#` zh$UlEGOIK+NasjqyVl8lh|6AziqzVNOP1p5yYIy_Z@#Iqhz%Oo;mWvnFaN;_ICO_? zkQ>QK03gLKI%yLqGDu{GMw`L}g$|Xiqm{ac$Nu&*Zhh(rEL=YR7-ie0%0OUxB#K?y z+p%}YBy19iAyz3%=|hkigH-7_TRM6J6`Qh+lq`AQ-H2q?!dI%(g4R%uM)9Uw#+4s0 zz^kJZTMZOYgWjca%O^)b$G z?Wq{Tu~-e`p$$F50F(OM^ibMaGZ=Mo^S~-RzCqmp03ZNKL_t*CGuZ1BSa(RLaBj~G zbXaTV+j85UsW!=|MhH*^292PoVNp?)|peETI&v4hw93f-&Y$u2T zc0(%A+AU;~Ez4*%fvAr>NRV&PMK6Lf5dd-k7!?va&$MO4fm&#tt${Q;g?!Nr9f3&n z3X?xV2;Rf!$f!7OI$%2EbSfnZQ#4Y%7|FOzZH0Ay!f|Bt^JS3%b)0O0BD-HZ2)IyP z7U2wh&-e0o_LwpWO^#7hg+eI-L=+;WxKP9s1R^3Tgj$cWH^P!gEXT|m^pMZ?qb%PM z%Ga5Ck4f_F!wcSHM;ZrH0GnVRa}G_;)gl9}?Hu;x?1Bh|cuh5V13iiJ4HfD2$GRf? z4BmIJ;f-p$0gOswld%n_?F;Oy19kpuVJ z6K9-rDyB@Hh-5mA?g^8`DY3Cj#%CH1LQtGB21W{u6qzcd`@H*nV8AN?&-RN)=!ZF{=xoLv{j{flXj6x&hKKK$4gz432O(7+%%yE^61GD0|=GSb1!*rUSGwQYdBbF87-834=>ICw~;R^^G-yE<56~i_gcD8Pn00 z%^=%8QCZw3;PYde7VBY40OCbm5BW+3zrEuwJaF%C@&3Y(;Kico>Y0Fz=FY(<=WKvY zrp-dNe;K+WISel8#ff9vPsPNpHtjuYRE7M-U}(h$ zA0yMAK{89?EM09KjZ`~+eED6t{+{R8#dbEmCju86uQwN;-F+|YwDmSXsfuDQkG2%0 zP2(t)3mEDfz^Z{k43$erwHs?H%n>qVt16I)D1edL2UIb*uKo)yAjmfI9`7H1I&Ny5&ZML z_g4GWw)B;D8rU+C#$FR9V4G|Qrn3}UtRP0ISQ!G-kRX6-SqeymZOueBAzypsT2-{P z$>%D}aTiMxz!l3D;F+O8Ar$VCNZ`j)=V1MM6mG4CnxLCn61B8R%M{Y3YawRiRZM-G z`-*EvksnhIWKF4+?p(e|Z0;AP%)pNEHn`=AAO|ue$+SpYNZWURHiHe>IPHiQ5cdB7zr7U7kAUIG9v&%?7__-@Y> z#6(*pI9{ur77J#1PLl33V5lSNHqe$yBAt$lyuB(l>U*tJz21aS`<}J00ukuHCa07C z%UY2@TGyJ)$6+~A%I4aEpfhu{{3J?}{Il#;7d58-*Z=vx2B9ch*Jp-a=7vwFgs{iK zA!Hu2m!IVT&IM@e$V!Wy4oI=311bc%5=hwgJUVc~_B?mZ>{S=2L1 z?-*3D1i<&_NAtoL&}&y9nSlUH0CXJG39xO1%IYX$^YQN zTOS%@QZ`tB7JhcsCD>}~tcWqOAMm^XIR>BE z#kPOyJ#ueC$u9PPpCG1#KrQ_8b0&w%kl4zY~6efuF_=unN$>;ZoCQh z`qUnnxA7;Cr~#w-g6NxPvTexcav1FAJoySb+R~UjsT-3gb_t9rXa~_X$@N*=*FJZl zBt%>pLPWA3GgOk+gmXhg&Z#3eI*64YE=6USdozwyIw^a*!a&u7kO`d%TY zOYXQG_dNfCY35veDtXFRzKHK0{5cHw4axZleJe--Ep%GS!2Mrrp>w9AYyd^fL@c*{DP9x+indPEn9?lN-6@xBH;1u6LIu}NpK18 z*v`jr$P$<>gU{>Q62WIWWCj8<+Xk}F)5$nuQO|D?w8T#FO{P3c=S@8eqUj`N@*hFA z1OcStt?ow&1bigO!lGKHl={EDHZxpGkO<);xNvTI>A^Dw$S!!A2d)ctRX74X~*AS;y4icwglg5aK6C zKx_P*9S{-6&d)?BBvMtzz7F}(44(l4vp@zMBp~vooB1H6%yXmv25lzc$sB_1kN2-m(_b zl8xevr~5n1-)tIWXohC*jnrw)^O6jQ|JWJqq5B(TA!c-@YzY%QahMfR1A#mpoN(Na z@$$2OZ8}NvPcFXjY<%v(12K8>6lAkq(#mB^MIn38gkwqx!`vP+r3Z^;9RICv?do-c^Qsl+lm{QFr94J@o!hev&)`=hyPfAx1pQG#6P#VplfALZjh6hliWOytNhxK^rX*VSVX6ZEt zk$42XBRPEUnj7%9HDu!9hkD}S2jb)-zktz!5p{6HA~=WF8VP1Y1_h+ivcp&?%Eh`4 z%T!#Klv~$4_h3V?B&B1!uMkt!4NSf(&Ua#g99 z_Y@q|*&||O$`xpd2m|-fY~Mnv1>$EU<5zbr=P8qH0}hzrpf&~w9#ZgS@~lk|D?c?? z+l26%?tqYu52aO#Jcv}a3+FoF0H~ps7LjUI`u3$)pH7?HfDGIGSYIs)Jj9W{Tr!0I z+uE{PpD?=Q9N*j7)h^0?EFaKuOTWH_Z~c{TCIgy`SVsG@okukPwIhIzpXCBk6C~@O z*+0txWoG^wIPg3~fso|@8eG%sFPVsqR=G)J0-;V1^q)`|$}v9<_s1Jw-Q+m@#bum! zc(H}wuK__o&u?9n5*rw^!T(8{j%hQrLPNS<$7bFkh(I%tAOz9vVS+CGc+iLJAI~U^ z`9w&AuIQ%bCO5_5P=*jD-ZibuF?-5Rv$KLHVZDK1m)L|}?}DlrYK&_ftgm5U40ssC zFk(QqY@o!>fK0>n$Zsdqwqiv;zH->{So&eJ6ztyn?1qajI2*IqpNk3Ilh9}|&JUSI zgLK&7&`+Su`SH=_s#W~()RXaxpIxo`@2NE0>9Y{YbirZk8OdmU{iu&{C`|<}%9!lM zaNb!bVBb$|hW-y%V8X;S+9yoHjgLN!lP|jk-#v5}Ty@$}sE-W8i9}^@m4@=DQD7_U ziSwwiJkT}?-#+J7-1gMVkhJFl$t;rb zD7rHdBx9;EP^HW<%Pt%&BNwkjL=tXH5DhPqfRjlgS1ICOufKt3UwjU4yuA>8{R1eJ zi_#g8Nv1G+=5%bj@rIbU-PYJ{i!G3G>nINNVd?veQ0FLK1_vDP&B)2s3|W?+(?BF1 z!*g%FjUWH~S_~A%w(2!)OlD~Z?vK-tJrcRWA-Qi1=tRfNc8-{C5pGS|0aYwCif*jo zOKX;9Y679kUWg%ItK;d{Uc+yG{}?`6+AOvd1os*!i4*mJj01cknZd!G6R>?k6$N?h zT7|aFpd@wLI|mLYoRXO@h=dttM)ZXHmn9L`#S4W#T()3I$NjcBndvd02N zTcIO+^ia!m_&ZvkQP}p5&t4e+6M@5Bd$3@S5H?NY{aHJoY%8V0A}p;uTg&6pr5|IM z**1WL2b?uwI`(es626Go+|X(Ge{6Lv7AX*gW&Nd}4mMpzsFY#+Leq1!kI=NX`gYyg zeH#OWPb3`sg`SZm3fd4vg@E8l%boQ6$KxWVBei?h&&4T6j5a_@0s=zxTriaGWy>Ek z_F}1o_VzXj5TxF~34rmK3R= z3FNxj;#VR9z+poQ@v{UVa7a~$1JMCUOOgXYBp56(FyRkK01V`PgF3d&%>5hfGbK!` zj-R<(*gm{4Elh77s##qYLGTd)`@n4+VBaShiD}WZVnWi^rIMX8-`#gWw)_)%qCUzK zkar@Ni}f2VUG%w&a738f)q=&sM{Jb%V}us$q#s%$iXTL>%aU( z*-TampP1T`<|QAL2Q;&{)2(D41#vV}F7veqLLCH(yg(*VzWCCsIN|6YN^iJ*#i9{h za@hqq^z#Q}`qWu)9HK_L*5odliwgjgKz-02qXY-%UU)t(J?m@`6i;ux6EgcBjM2;_ z_MJ+`i)satfmNuz{RT$={u1i_%YpnTrge4WhO*#FpbvHSMZ zal!YGf|DQ7nkxg}Tv_%;BEtZn1}7HBzn2uT@3*eP3W2A`_OCG<{^XWhj@@rBoOAqFP#7Y4OLZy8n6F9=+oanf867I` zNu6Hzg6v5%3SDdqOBCg*pr39mh9&*Oxc$i|@aW4g%S6T1xTlsNGRCzf;);EmM+B7d=Z~%%i^1p=Aff! z*c9Zzn5AoGN!k*BOOZ|kBlRh|>-b-PIGNQ?a2%N)_{6{pygS&7oq8tWlbJ5KMa5P~ zu(ag{f9u*CvW`AFD5b6S(fYUAe#TmhH7>ellkGnjn^)cy!`~{AqaUnAx(Ya=o*27#SWGJ^^pOjt5Rk5TNaToH$q!F%i)npkbl% z7Bd3__4DVV3fQPCA(5>$Wu0T70zx`HkmoF9I3fBe5zrCZ{0OEFd->KRK@h32c$_8tQf}{E+qs=M!3RY2uL=C|O3& z)!ubmLNU^}ekn=2=EAfFON7$0znSMC%9aV-_N#kv@fjEE;575vcAL#{?G0C9lTEio zHq&J^vki`7<1D+&$Asca()#VAPvJXXJOslWjJ55dXglPKC~`oM6JhUw7)Wy1*&c{W z4z&;7M)A2v;VxT@YJLC*e0m-(`q6R7IwfhBOJzIp$EW{>m5biO5nn$Dl~K0fxiTWQ znkyp8@*9Vedv#RfX`Fb`o%r<=ua2Aj&sl#KjymKE*lNQ~1O<_)nRSw8J;W)X#ZlTZ z&WGojN(UYy9-RQG__|M+L9-m^i7Fi1+~V+JF(lgB@aNb5flIEx9B;6g`q9uVMe{lmsWQ&#=hFq zvdNgCRRl18>kuE~gjznXhiSSE76NEqe9ZxXB4O&I^nJp@y7u|I8+1N&zGUf-jEtb8 zqa9T5^O^S^4F|gf*kkWVNr3P^Yh{Gzxk1EnmrJq$IS!baKQ|9gg1!H|VRYt^sFLuk z9zPei$eYsOM5EH5D*gSezmU!Ec@jX-k(bIPQ4!-6FbE)wCvyhGfUy>7MhrLDF+fB> zGg=G#2a^QNjWU}}h!hq!x0$!8(O6=f_~URIZC0x#Cu$i!kl2-tXlmPf*F&yN0f5l) ztRuI@Al@}Qyg|>^4_I0ZjD{5odF#L;4M1!FpuaKUhxuNckib^mtS-<*apX8{-OcV~JU&uZEC`wB{M5bQB`KO(L!*<>r z$w(c^Y(}#EW$*t7(>9z6)GDYKijujPM@JD)Mpe8f-Gw`!{5wv(_*Uc%N@g#Pt!D>+ zW`FFn`@ZPTw!^KOKt38l%8Mb%{~PBZD72#`G;L2)u`L;$P5uqZvJ~!WMC7|mku==S zIDY-egSh~?mMIR{dY0k z-;0QoM8k{m%f;|U8bkr=sKwK`{GPjT%Ok%ZQ^5^C*dzAd6X$>XDCGMo2X36dXz~Uy zuQ1wu&3=90N-))RB^@WyF{D8z%M;{9$zMb_fXPG>D{}?h_1quvz@MJSz|d&Ru3Y_J z83=5XN@4f54$Mn;W3sdXD$=S#Q*^EzVipCY9a?6$iS)DrJuXILE}qOU$G?^@#~$4i zF|Tbh+%lgZ`}}P*Z&$MM6+u3s``HG%;&_c%jnPTbSrdk|%il-ic&}E(-+Py1LNbQ! zIwm4s;rVE(u*pHSIC1;C@qJ_H%`MsR>hIvX1^~^+_7|%?u&K~m4G!B8wbFBNUEc~k zHZ)*@#|C<05nM5O7B-8geEl1_9`hBUO0WK?DGt&*;9q~}Muctmc=spxSr`RaYseD> z6s9cW+cZBSQ(Xr+%^P35zmbeaQ7o3U6@@iMl40n$lL;Z}i8OD8+Wpk=FG`lr$4;Rj zvh9fo@N;bE<8j!^CtU&}{TY$KL3jj?gOTA;v=d1%t$wLw(y#fmY{1VGU69rY8ljr1 zcM0=fYK2C5i*>U`LsbVw3m__yFS`h;^$Ieq$9k$5sAMvQ0CgIm%{KK(Ne$UNP3tV} zLk&Act?=2}cCbX{zM3{T?G!NJn(yQTeA>id#wnZ6nM3)(hFw{DU|m4rl7t_{1+6|h z%RmQz_>hGu3)s*5F~9FL1Grn$YU^nAgru#`4|@EQ3>LH5{eFO9_k^w2o6TT1mtKvz z11&p3eSBaA6pGhupB|d)K|XCb9P*upyI_M8+s-LWS|Y8r2EKjlkMOrY{mp+^$z%+- z+;RgBI`|;O6Ip>=)ry(x_YIoe-TF~$$VhxU>%#MJ$(iQ@-80d1%#To>HCLL2n4rr% zc$rRVS{0cq)ffa6k*(KIeC00~diFuM{Y$akRvY2It4={G>PUvqGFNe^7jA@OWoxJp zmrx-?-(yQ#6>chvS3l~<(LcEkiBV9%X*LL!osIz35zyuMU4h8Win zMYC8^s8>;?nq^%BP6h)Epk0lv;mFVn2X54Z*N93WmFZ~5MOR;mo9=qh*SVLneYy?F zxtjtT?gV$@TvSsX@_RaNlt$sK{0P-|{(l8^|4a9j}m3Rz`i#gN_dCbgY zzyc{Plbu1J^tNhnSpmC04{LrxN_A}yfTtA%=!kV z$78sB@+{1a#to;cx%a=x-`l_<^z6ge;=i})0s}A8x@3a;wJwf7{H6N-)>x$J?|dpZ zzi@w}A*|PkFnHVBvLf!oze^3QT0uIM)*(S{X^BDy2L_~$&(o%SFl+zCLQy4tjXnS& ze*T@zT9yh}0$_H}TL0j{py&+{bs#5zKVzU_=K$DNK#itMwr3nQ)dcD6g|RE020D_M z8(g{rY7NBPxJ2>AMnQyB%Q!jwQkczBhQnK8etB78L%oOaL(lcI2+HcG_VO8p7k( zF2cnpv$##!L?_c(*eF=?j^6$N03ZNKL_t)9f&Vs++WbI$c=&#WPr2pu>c!P5_`{j3 z!?kzAs9)I~YlxjT=o0wW{2QpSDJNw4ias23$k(v=qd*3D!%gSluHW8{O*h^Qo|{zh zD8YYC=|)n&AczikKk&@{@!kj6d)_?sjnvTfg|DIh$=zA2LQL+xfnN>rOvbnxL_peQ zX~;*1(fi zHRLYF<2d!YYw_62ulS#pAvqzPfMX8&49+|DFytfvVDg|&PcMc{L zFpvOu0oSbt(~=SR=!gseYCx60Sc-TU%;zNg&xi~=*GbU2+zio-e;?NB%0j2Vwi?UW zV+G$iZmr(#ZTUZuU+wc3!h6)kYfc4MELnmNIf>CEeCx+zxMcEdtQU65OQrO{#2nuu(#v;=9EOyM8G z`!d{zhS)f1%lhZ>Wq1e?h-wX`a#`94`FGao==gaIU85=-#8$R=gvLV$vQ$JANV7X~ z5L97KcZRKT`|z~De-<|h$bf;x2|0%l>%1kIRd~g=9@@G~bLeHDvrx`&zuOKd3X|-@ z0YH=VaLBpZ!ninJ&Fs}lS|g`EE{HYFJ+Q|P#Q++2*}zD%4ttM6F`2(e145wQ3ArkJ z-6n>!kgDGL;NEJGr~d}SE!043DZmtG#R{9K)&x2h+0m97(Z#@^^J@Ew0zxF!BHrofOL%xDq zPnTxTs6!}oR=kKp8(e$xD2)7Ojr#ZvEApUu3LedNTXKF ztN2PGhhlFZ;>iXoWaW3xz_-u15%)gxSATuUd3wO{U;jGx+hbQmsw(J}Nv7d>RiKtb z$CP$Vp1mFtZQatk$2Kp`i|xyb*s8IS!j;s;P0i2&?z;Pz`09}-s-OrT!>rBGbL0<@ zpEwu8wJ4m5me5R-cwoHvesUm4;Ej7o)$6Fd{wyjFTn*$YU9893VCn?id-=~XDHg%t zs$N0vM0VL#?Rw_5(PS2Pzwl?Aa^nqxJoB~XteKcQZ7P2M*Vj;}Rq(^FegWV8++HXQ zjF@29DCP+opuN*P$12n(mFTOAG#%05B=yV8=`+c29R=vseDNBMv zu=P^frFl|DbHQ)9H5;ng zxPJ_s*;-v#$nTB+Uh@VEtcH>UAAPVN4BqOWm0XhTK;{~d!E|+$5)nL8$>GLjE3k}W zbLLsijmL4xl=U#1E#|@>X)fRDfz91EfkmsiU+vwoMmm&rto8nc4mRe!{_)27M)T(2 zGn4}U^SzBIHLFQRF)*2wyJ{7rGASYFF{n>cWe=>m7bRn7?Y&SeNeO_60bzS)@WaC+ zW@=wm82%*dk?5DrW@Iy!N<|?6%5lNtk^oo~!^OHIg-C>BP~?bULilxY^vr0Oo%1|( z%&#tfmIf$Inux^_bv=yaa;TvyQ98+mWKT=$hS3AiNrf8qO3PoEp>IibVOnQ+;Dg!0 z%{Se`^Tz2~RY8+MTW`|j_$&-=7n1RgwzWisY;154njqz$Y{-#Y?`u7*1h#=U7pG`+ z0t6NfpS-{ObpZzj4r{24Q!vKB=RjCTtA$IgA?k(toB#_h_`eBTK2w4a`CR)7*YblH zLCffJdgeYGlBHaR-%Ds_C(wYKATpiI;+}gR#+lzc$5%z;>p$YW8}C;l zPl%xSjbo0)7Y;sHIu6=WX_26<)$-`-$zr`tH-?*PgTofb2A!(bli?6j*6~RJGsPB& zbiGJ9#&hxJzyFB?_B{Ygm-NYPNpHO?vd5f)rQRes`6`@7MKf*VT#Y_$P=>O?Cc^5C zA?4QK{q0$dJoIy*q{rmz;7`rN{PWL6am7-U@)ho2aMUglIL@VK%kKw61Ni(o=b&#u zM}B{QznyUMm-fdCe|;aXyt@>8?Y#}wpE?ocV$~?3X+R@oEHg-l&srsPw4|iAF62SP zBv}0ejReE8)j|NXgUL+LE))J7pyIf=>#1k)($Yov{&$YWzh8P2_doFj-hBImar!jE z20GZUq-9QUTx_36VULb(Y@KXJS2PNzOhGk1T=X)K>!>Ek2bk#s&q6N)@JB^wcg)2 zl+gcL{Qt*{n8fL~g^;V<_!(uueX_YgT(5NF3PaqkIVt6!M!llnD!`K+FmjjHvy7BV%UMsX}E+Lf71ks8ZP?Enq4;Nl}InF%kWFRpaZHFC!)JEGP z(-lL;jiBm8FcV5UU5E|W z?~&|IYP_SPXyivws^pQG(1m**dJf+`?^X;@4$j^f0Ed2Vf1LR3Z=hN%qAit0y;Mc2 zJ&qY0&O-ad32-8;S+c~zr%FPsj<tSeMISxJSi}>Ro z|0bbAbhGWzar~L+ulJx{U?5TV>(hkdrM=8XesT*#DVnspaEfRINy6BFe+0P)t^?|d z&M*VM%!2*aae`3rWXg#ljfLv}z=mvXyQ3j4HA!Zyha zCPh?DRa~Hve6^xzQbCg-$3fK+l#RW#$%hH&*TJdS2D#>L8|&!pzO(<=@=EB{^4IZT z{558|O##4|gW33cOD6vP$_U8> zD_xGL4YCc8P`)f&Gw6p%0VRkD=TnD(d;yAbXc^u?B1x@*s?jBIrOSW|oe)@+lekD+ z6vne_>W3~mlWi!~^T-u-a1qa2#siz|%=kdl0@(V1ETcYHy7qSZH&Se!E&<7aEhoS? z6l(m!)=9naiA$X&V#tWlu$ z0Aw7LGI}jfKyoLM?KPD!Q=_-UJB56W)3pIkh+N1su@I_Wi{T#lH%hq{+M%Jn$r>o= zO%URik7~4+yr02WN7B5O_vmLKqMgHMmVBn=cpeq7A_S;MG$?Z2pMP##GG;+gmYB@CG3B3OC z5Dq)~bSz#z;ForImRoPJDK0zzTtN(EY>@{{nlcTuHkl(sf^-@a_wAo(SRajvS47?n@xP!%4kr=eUoYcTP2d%x4j$Nr8+Prnn09mNknP1EtNKd?VKXpF6)hw z3KSF40Lq^RWNl2?Zumy6B}5p{uZJ>8b11XFnnHK|*=hoTH9G%sKc|Nae=a~Bnl*kV3S6~f3I3kTnJIvJO>?3#oI7C#Hb^Ex`nzzBnvy|F z4L47=m3%PPXNP_gx+?R>=KHhykRg0no5Tb^YY70x+;meiz4^rl8e}f(&;YHMS0zIR z(it7(!Rj)|QL#d?D4aGGQ36nvXyQ4C~ z%tE}-SYXYF8SvQpv8`+QggV)!K|7s5x_-SmnEYqe{H!CD6Y&j*K1h8IHVZbJ#MZRs zS0UL|GRD@QeSNX?B4`?D70PqL;+-1f+g+6?h0c#kV z`+52NeE8faAR0oSD5BYEj*2#j@n!i&g(Ibo$)BrUgRODubw~ifYcg8anyKkMw33?k z{#sPX0v0sNP0L_hQcabCF7B^q!d@BY;EAbF$j!re*A* z#~;Qa2OkcUBlzN(XX2XkPei6-2t<-edWbk4J}#DU!h_G@^}Z1}$qrQN4(er&rL9Y* zL8lyTR8jcj@6h-3Bj{)}aO+Ly<1>40japHOwDn>Ejd~e*$Hj3cU5W=EeOWScmCFO# z+cLP}+RL#1#K|ZXM$y&Qj=39efW+h;88d4|W%T*!ebe?bGnr0MAXUp}@TV_6dm<1b zx`DsH{t6D-?+_tUMxt3v{r+iKvH53FE;Zm)s&L9VB*@W;QY#=TJ?QL$pkbsPp?-O_ z>Y!Y2plry5%DC2vceEF6L;dKx^-MJ0d)0qN7axBtjz9D;^nJVxQPBioE3oc!FPX&e z{`xXbzUmsW2|xb)J~;XCy-^bBUk?QiB4QBWSOmbdJBc6=C-WJE#RkM?M`{pYHiUtN z%`P=4lX3?F7pGoOmWCnciHe}T%ds^6{=wV0^!7V(;t5~J4x4X+i0fczIFBoD`VAg` z?nP8(sLWV%Z36=RzZww6=xmIPH-I^@81`$QgxxzPU>XUWm9p#=woUW2p$T(@m z=S_LWh8$`=)B3Z)SqjTPyN&w|&68l8A}H%EZus-PjZ{1?@IBRcnB7zI zmqwHfdfp(;2w?4Bf&eZys*)v{scVZ~CY_eHJ~H$P`AZffhQ2N}dcylM0+>WRGt5VH z11c5yJ2?SF5V#8I$oXE0(%1^f&0JL@z<;eG96!&W)4a)a!AL}`aj{Sq<~94V2{#gQ zwNKJQ!~tv7hyaB)i8yRi$M+?5oAmr`%{U;{$Tl^-!?yk|%gqu^taEO1)WIsZfrf5( zy9A80wpnmXja-~p=!ph~L!krtyZNEC28uH^$e5g%4HA?Gp^qIxVkDlpg~lp+rud zbFSGP8Pp#7`$llYfnUMmg@FX{yiaY9yY9XNlP69U1VHbS#SB6Tww#VJiVTij7vDMI z+n9gdO+d06zj)#!Z& zK%`EmSVP=xp!k=2(f9iY(OGZc)?ZwJ&+fl1%0nX}zEiK1;Kb6n_rYiIwI5z2)A4-d z1`dAoy%TWMVV^~zeD>=N_1H5pRBwY*tH5(=NTZGpl5!&~k2sPUMH*GqoCw@V zL`b{C#X5>r4=gB_sPAF+M2X+;dC0~+)LwfEL%%p5C~IfH<};?@iL0+geW)J}5ft8A z^N$ma;FXUT;>+h=B<;fAKV%=A@uhvW@85AyYD7?N=-?d=O_Akq2c=NRM`nX)SAfjj zkZv8Wd?OQNNq!o&n=+``X(4q>LDS3~<6ET)&kVfA=fs|kn#@hP=F!LT+`I4Ky0cG3 zCmHh*py+tG@X{Oc*q{EYoDYGT!?qxBJT{=0;M9!6cHA0bHDLWz9G`BVfSua9F*lY# zs#t|XG?dqA#E(d5*6{#R@K(J+Q^NE2viY^zNMkUp32N=;^PQq`O7^syP=OXCz{XYM zI;fWJ1bZ%HK4XHFCi@Z`usKLjJ0_1Xe13f12J&ZMBX)h`gNZ^B*|s)u@ceUITLvQ|qpJF6n9?#quv8HO6XE?Kq6qPrUz6m|$OGWx z;KO2DB2fw=3vBUY@Ij}|z=4FpDs|IEI+z1WR9MI|{w>1MRC^X@XBp=T{|kKYkJL4u zNuHfm>ayGc!|?Vo7|RA|Ud8q~`0&4Z$UZ^Ocs1L)XV-vrPa0%clMs#?4f)X2UbXCM zouT0p_#4@@2AZWUWG_?5vdi5{3UhJO`AYx2(Ha-OD?Qb!VkQJ61FLH1g9#$6u{3p6 zy%y~f(T)rg92qSK4t=s30KPDkx!wSkQHLxLvq3f(448fFK zm3@8Yv-{)5`PZSRdm`e|lqpeLUPCwlFu{>|-oyD(?7rg;c>Rrck(@XkH$U||9I*Lj zs1N3}3&xG2O4^9);EHRn!xg8WFAgZX@m5G3csMFk=Za%+s|=Fsh}Np8{P7+P{`pCC zJ9S)h^;tOlfE`dC84_p8EPgOw!{J{(3D3RqR#RlM#bz7fmg}xSte(Tn*|X3&V*@iE zUgd6;ux6&(iK90Xx6JUR=S}y5?{geJLvjW5la3q1efQjfqmDQZ)Ov}n{|O|%dpU+C z&fv&DK@K7)AyO(LS);=*O1(N-XMn@!>mcEJNPAHX=PMX0)liEiQRVn<601aFmc4;d z(Fy6ORnU9sH&OcVpR%_&f9ST;e}etC-xec%gVLhNQX`f4*pI(pWC#bIcD9TiKjFaL zaNe=|AwO88ZXHV12+CCkY$gCOee;%EA^*1;0MgR0L}EJ~RDxI)p770o&<+x42dHBS z@meT=1eSJG8%MY_4G#s!!vM%>~S}cYg+Pkn<`$TN&C6FkyeT}6jwap51QjO@jYVT;+lTn{N}Jvv%3AdhOO~zRSz^lpKn`(L`bZ( zIiLmr`X=6=D!W*sQ9PXM!?nH3k#F*p4Qvok;0N8a(8jVJfT{5)GI9(XNUW>JZoaeD zE;jk@F^+uA$6ozsg8(2Le)vZ-Nv(6s%MUfGrHZiZ3Cr{D(%JHcN6EY=U8q_^Hj@={ zAldtwOhybg_5aBYUmIUS#Cv5cl^$D~*T4naqy{rBp1)hGrK)EKZr=fNQ|_F+0=%KOnSO zhi^Arpr+@e>wy4}H4dg;ZKF&HFwDvfoOaN1=x;cKQ!7z0$Uc=tZ4?1R#6jKn8kq+< zdGK9UsK=6s{4Cz?lCi}hEdhjMns6lP|JE?O>F|xjXt=dd_PaRqAOMoFDw4q)Nm8i~ z2WCS>*~s0{+NE}$XfVM*gD|oTg)*C!r!E1A)S7kXgI84 z{(*0N>ANU}G~2)Q5r^P2S%6)2$5$S48PajZfrhDd5mrr1$1xQ>+Dzzh%Qh(@rmcMvPebvW@9ylO)v zuk#d}aU-ZSYDlD$s62iP2JgI{mO}RS7kAznH=p$r3@=}y6Fp^QE}wq`{q-vLIsKnr=9Fi?_t2Bi|)f*Yt4fe`)$k7fs3DXJu+FU+2@%9FaHG~1K1mg)I7 zLjrUOH?;_w)<83qO5kLX@zv)bVjz5`Sa+z8zqM1yc#Nj*p)f|@jM$I$R%-|VbSno=G3*`#$7Zwt;LyH=?zqPe zjuOK5OwWh%lGwJ(ujR~zTErFPXd!C&<+4S1v6vIQOpl_8%Eqw-zSBJ$X@}g38oDAL zW<=O7tG>tXEw$3&4BxbouEB@@Uz~sN%}oY8h>nbnA1`jRL9TPd3->n&Pl~Z^)CIz) zAW%A)LcWmGNq!t$QLRbK9)kmFiZd$b&si=|>EEh2Z7bVrAz3#8}dSt6?pbYtr^vsgzJGlw?h?{3F~F)`(+qX$|H5w0<&VdVA;dFe|iV}@}^7C-jPM;{9&Xl=DQqH?rG-h@5aPa_Ol+wE&b@z$aIr3M9$z zG4i;yAB5HG1#hZl001BWNklyA6X&SIkl@BFWz`Hk~N@^&j}hR@NK;;S@qs$osR_z7UFw{?18h7*&Dgu z5*+f1q&!(enZYHYa6%Y1SkyVq+OjA<*3{?7BQna3x~tR?6aCamitbDmiVWnorNz_i z6QXD&f_mg22;)|dO=}m8C$M~I1i!lXQ5>-UPS|MkjqyJ>-GTd`e8vv|f<0$Lk!Ft( z+SMk7vJ&0;8!x8iP?lK8Y}quK#b>)FW4m}7-Q1WIVIyQsyC$uBL}%6L3GNd{I{oa| zMwNOlzOVHc)i|WT&}sWw=Q<()_OJn+F68i=ZihK?NQ=S#+BTiouT<@OC8cVEN+1ly zxSDnUA;-ZRE21KMt zFVc~s2nY%yy@PZNT_AJ`y|)BHNN=~7xzlIf|5&&=E@I7kkq z1j?uLWOh%bKQ4q$3Dk_AN`Kjm@&clfsBjFJ&GR`#2iQ``4gqF(oIJ?>e@-N%V@ajb z$|aDRKkK`Uc2&KPzazpx$T^qINT$#CZ{&^1Ya~3$Ux}Ka=~5^= zaO2qYxEr#N&5~tSxp_$4)CPWLDXTMf{>}&;mCJ;LZnxpEbjFI|bQ)!i6O4j`RO$#5uPC3EqqlkcOhd=Q~v2#JOo zw6r#$bxbRo8X7Qe!dSF6H=?GdMuP)CgS7%&WID@rcxA8@{~^_F?hWa+Q_XT3HOZFT z3;?3I_s)Oeg3~S@c8ZQa^;n#B_Nj=4Y7p`h#WFqO){q;^QAS;;4(4{@$WxET9sjrw zn6VuK)2AT&($g592;-D9Peafj!kxF@fY+aW9uCndww(zjO?MVuP+-#Li0(fVnRpF6 zg)Gu@=OMW8J*4NoiS|SU|Ged|*l2?ZqW>R=#_-sa&*PB8&p;|?GeQ?aK_BkE<*(Rl zuiX)d*8wh_$SDra29VutvB&pz!AD=M2I|IQ zo2%}?gzxW&o+7YxU;rz-lTx=Y<%(F=%Z>#Iw*mPa9E#Eu2ute@aY58MOi&D;~|-W0WrrFD?OzBleiq%J6NO0htm5$B3H$g^aTCvQmuh4fG!*)$Uu z?PsR~AsoN7BlBWu>_v{ZstuUuXIR&W`WUep0^%7Ck?0P{%ylXUdXX1fnL%_+GyZtj zeR%Nk*~0{#zMZ)r{aF(F8DvqKdK?GDx2A=nA~n2qD1la1@}vZ#?U8cU8MGOCiRg|P zj*cZkS9_4P`SIb%!0=$9DpnZv!sYk!#>2z!>L-_ODv?nCG%Y)~*{xj~8jL2MhCQJl)rY*9ZEryvXrJH2A+HY1P2gcAaH|88YPRk0LWB7-M$E*vNeRqaX13~) zq;Zfkj+-+ea#*#h10TNo8RpNMhtEFx6w8(@M_*4La;fxa6KTJ-O(VI>9}3Ehi1u-< zm@sJ^#!p!X)7D=HEiKJxY^akAi{T057g63Le?;b^l;HI+qfsSE22G)G6xaRzHe7x2 zHI-{{xp2}MC*ai6euqT34xvC?OAE#+=`biYp5@@laWGKKVfQ_MfVbZL622{WfxER8 z#rNJq;gdH6LZ{Oy6*J}1BtvLkX?WatY`n{^SpC&J%zOJ2)co)eq&M6c?*2Yx=PpD% zvk-l+&&EdUPR3o={t4s9)q*I8;|<}^nI~e_>{qM2c&ba@d|3JL94lZ|CVPPS$ z4Tl|d)T>1U42&tOU^6Gt!!uB&?o1Jo@c_48aT$Jl>P0BIBUt~}hv6@mU5WMLKBRI* zEOs0`vZ5ayK{r-s-FSClH!>-f@jR+gUoZ|PpBG2%EwW0GgDY1Mgh2vpqsO6_LKK49 z!)~-h0vNpS&sg@v-R0o)(qHU{6OT9?y{kHekW8aXK`&o8hC{Bp2G6`Q2WK9#7tTC* zH)IAg@;*!$h={nu9@MnO#EDnvjig~%NLGVf4m)CpMlM@KUsnp<%ah2Yd8H&WYPg~$ zDt#YSLR1)CBya^tP_J(T8xa_Cxy|eVnUCr`lTh9?oj#s9ny_doV*8A15g2jv@{ zC~It5lXa4J384}&H4wtii8^c*ierq&hk%S8ms!MOXn2*PfLflJpy)=K!c!Srr&mz% z+@l}^BQEkA5P(WIl0j0dUvAqjhrMNmEn%%>+4&OPC_6$^)*(_O)m3dr&AD7yRLtSU zWH06#Hq5OP`8 z_c;W`koO7&ar$&Rbog}qgHEM)8+FUWMELerM$XFaS9F1e|!%QAmXA5e+8P zF`0W}4SU&7n!kM2u>#v~y9-uj-SBU=EfB4N^T|8NfAmJVW^F%2I#MX0FGnf3P!hbraz_@HZ&-^&!|Z0RPH2F)-&P#5Q_n!cr9Lg^F!>j z?{CpR$a=V%GfG_FdgImj`5`}n<50es`JLUXhRs|C`%FDc&Uu;gW-=}QP~THD@|ocZ zyyBo|^)l?e!yb6+i=_yR+W=SIe=82(dK35ySrpwKu<7@eA>e%%@NwRY55HWFo@G7A zulN$4fj*hs7mT$aUpE#>7fX5$f~AZMAmYB_`ie{CdC@dk$a=hIHU0qnZ$FB8*Ifvd zR1@Hkt+&L@f4&fXE6jc~s9GQ#!_ha~f_tBS7JoSGr#NZf9g!MLnE=3?-H-=~)+k&o z%1i5|$-`v-)7tCzwxgqUK$r)Gw1d9x6jm+oLo$_zmun49A~n&lu^GbC6x*Y03M~hk zke+2M`3My+lAjyWD+6_3T@5b0>ptB7#B=|HBc#UMnzU-GU_)CjI?p&;*T#AL*eVvs z4)JEu$3v6=Ts`>*hJYPv#4B}zKHk&;Cx8JO6u&RRqgIQG> zv$CD6a%)_5$@(RM(e}P_@*~?!xgU9t7fYNxUP*T2rM@04ASvAh2I?;LgDM}VpT=&o zJ^Ts$w60xBOoaPMXl02hTr6O^--n0a@0Py;w(h1CVJYFyRRVk`NNXzRZ+^YxxMSSA%m~3pa_&LR|EXV7o1J}6# zgxJU-;Oqbr_6W7Hzn}0eQ38?;2@Uf-Db-6P!L}aO*40Q2S#-M%gvJY%(uCQF`D_lc zcud&+d>?WSib4!jr9VQzL@xL{wp1}&^pYTy%ZtHd?Tf*H1P+8CNd)0xC4^|0>heA` zp2oS$nmUvvRfoYt!WwEB&Mepe?PZ#bzdS8V+w0W-8aZC+$=4%gvu!y)HbJkd-dKgc zO0;Y?tc7vP(3LTD!@@x&=E*AzgSPzZD!~f=RUE&E0bdUDKAn%3{{0eOeC`D-S-cdE z)KmZOJv=@?8rz$&>2{l7+wX0K%{JQv%?%AQ!LC@$%Au1ityF+F6u_ky{0$G>@KE`J zxdtbldjgIQiFW|BV*(>0)zdhxwCvHKqTqSP`T?y1w^@rO`+^CgrP zQH^fRBN?f0#8G!YhH;ePWm#>Y2WRZI1Cnk(LNkv?YWZqJeL>{kdlb2^7GUom?uzUG zay}x_0)p{cocjAqaLqsN75Gw}6|nh6>*2{K?m=C16I`AcT!gC2kfVB4+e%rvL)FH# zQd!mBe=QqG7A)l_4<5SnM*Qlq)JTO9UlJbK-q&_V|xOlc)&4tRX{3MD+-+l{CH zISZfN_Y_iJeE?T~hfMr&Me7loz6IjD{tWr?8zPxEH3s1gxI_m*TKh~V30wRavqd~X z)GT`sA76R`oV0drY%#ta&))oZ6#E8INautDzzjbejpN)q?!{FPJ%|gB+#e_YY)7OA zhRQ@aY2ORDk!X&wPJg5NKa(61ec6_v3-57yx`%k6C>V*Zv-oL>Lr9og_Or zNEq~B<4_da#OkrWKa8>7fOKdOQxXmiou=jbm^Rx=maPfMD9LK&qAaJ%9FOWNtPWPz zd=HDJ*tarSw0VPJr_Cf?YNvHSOA;gYS@Bf;(}NCI39k)wOt;m@62z zga+j?w%7*;KMB?12Q{t8n*o~Ad@lM=MKr^~q@W)`B2-3RSaCHKh#OX(8(}`b*1=a@ zTGeW-X@IMPr>b`KVLQY^(!)N`gouBC`60(c=NxY9LDoL4Qzm1BAU#M{a7iVq!@gOl2gv&>nAvUFm>X-{-Zm%}=@v zs6F8Ii38{6B?_S(1*$0^WHFPyOF+We>l6+$ta3)&=}b!721T^QCx}Eon>CwQy=_@5 z+b+5-HOTvGq%Q~G5a?uzlpzD!;J^kA@^8~)sSr?QL#gDh?mNpcHUH4fV%ppUGL-sN zHS^!@SG`F4z7~6~5E6$UG5NXO;3g2zAv-Gn!=vEl8hb-Xr?PnWgAeh@LyzOlmtI4% zqxb)w$N!p7_5=bLGr0}hZ@)Em-gOsjIAc8oqihu&k|}Kn`f>3&f5D@-JyL!b8sX#4 zI1ax%@krE0Y7q^^*|;UnP>>?orP|J=>&31D4{m(;ejIh=sle3r;Tbm`?pz6lm!5#r zw`z?m1M@FX%>4;mvr46I&`bNAd9S$78^0IA6f`nR!v@Ade%wQlO+Wl@B3rt7P!^6y(gf3?PD$AP}B`Q1YhX&E- z_lm0(V!wc4dOU0Bjps(@zKS%)C& zDZ8x-{#1U{Sh9#=V83~{L4u7u6^eE|KB2la3YQwo34jl z_u2{DZoLIs$Fu-`FD^R!FPL@vgXPQRcR%Xnqj170zeRnl9Hz((Ao83 z)_49t{)&q)x(2T48^PPs4A($EaxXjvWGW+VE5^!&_H8%EssDTwp-d2gun!-8`W~+Q z>5f344$-|1#}F0t;xVLW-GFF5i;K=X6G!}NU-&&)Jofl(9D4LQ$QbrI?Nm)Pgl8WA zCpO<4jl!Z9`B7rA5BB*f2Iqb*rZ(pHqOPq5LqkP$byfmKcf1}G zk2(uOQ@@8)k?YI=z?6q05rU&#n%&XA<+_rBjf}t@?%@ytg4@tp5}Gv z*;HK%9TBS~A!d3$^mYwl(HGrFr%LeoR63c@_qxcBVc=khsI({AD`231g`lOjF4>P8 z{+c*0xbGo6^u+A{X#n8zc;S=MYu=0puEhOD>Z3wbGbp4PBP6@N#sjS94`atz12zuC z(afo@GFXce(WZS@;0#M5CehP$JQ!rrqL)>Lr%FIljRsUXC)uAP@dPVbt#NpzY+L2H z1vOnZm*OAV)3XT3&Mt%+O$HCYzJf;qQLLP0>YdTPY` z2BafzuZhA<&#(xwR=0>$1q{^@t|d2GCtv0Wl%KEBWjTYXx|t?U7_qA=nU2)P$hD%F zsMPpvXBjya5iDK440qmo51x7WDfD-6j{0|a=-2*kkN-EXtxhQXUQAeLJa*dcd)Q;2 zy)f&($8rA+cU1)dz+t~T3@4v)G#X-!h)3&1C!eJ*J0ii7g@jPX758{>#2LTGo%cKi z_w*U?*VVzZdKrdZc^W8c&w4eA%U6xxeiIz>w_7l+ehU1F2=2e_T0DI6vG7G|5!mw} zWc+^kiaDeozYX;PKW@G8I_$X3hVUbcGtaveSKs=Onc<)YWQXlG#Z!;ni9no)MFegS z>;KxVQ>k_i7e|rHD*s5JE3*z70BAd)N7~d_|Ni&G4`aXm4o21;LdyY%;@0b~#-0gb zJ6Vl9xxpNsa>ChXOk@stBuEjN1UxMwn-xk?{UOe#dllar0uS3t^p!_~CVSTh7 za~^sVL>M8|}%fcSg!I=0)DRYmpMNCLd@!AJ1$ zV^9B20|2g>Cm2F)TbuakzEz#bCX?lWaHMmn{96NFXDe}V7fny z7Wm+oMp2_CNi{`L->lB2jTxsg6OF2)o;P#lrZgc_ zUg1LC?Zzsnh&NMxm_5*e&(k@izN<~Dvabo3gWty5F*TA94gjlK9{||rS%Yi*-A%7Q=H$uPC$WmHDw(Wg-r~@W zo_{WvMZg!38XSdyLLvSh0y>e9+X4;Yr|gldGkFuE z+TU5yo<f}l$_7$M zW^y8xn=?B1-|Y&9d*b?*HfdR1w&1G@s>6}9zd8^XTzDGlV|9qf>fjaxz@@`_gc+^F zZRCzpTGmy-!M{BkkG}98JkvLTzqS$HW%Duk5(f;e$%){ds+-t`A6<1Lw%&4AeDvmr zxc}Uv(EZT|@FyC9oqqzSp&8z#^N@b&5v&5HSz z90wPibt2Ba;3N^a@doPPa`Zvr0#F!0 zz7)b~XIz16uDe;@+wJwEb>^|iZgUW_oao6qvy0=3wF^gu_n0<$(Hd~D;7>1!{+_8U(}t}i9zUS5mW2XqXku-{4N;fm7_#YSVBks%pb*!Mb?*BAC6)}$pt zapI;uZx}?r#(6S?P;>sowaGS6l~k9PLTMf>o!@~~OOo(NCx%!uvu{*4L)iZEnT}{C z3Ct?Un}%!tx>{WP@T0hY)>Hq}0Kl4cp0~PjV=-phbQFqNbaixKaAhabef`p|Ir3qh zh6#6!Jy9r~Bi!2jUThky!IsfDCi}vu_jnOz)@=t7k(4ci#)cCHRXRjVwC1l`WifeG z`NUd{6Jr~-IA!!b%J#CtUoMX!HYE+Rzg9R!yptZl3(0PLp3Wk@Ho6kaHi4j&pL6Lf zN~4gOEBT0CINSY>j!nSWKo|wuF=>?s0`wtl9rU?WGow_%c#j8Tecabec{5c_HI%q=nbgB#%VzIagz|i4~F{MhF*MoE_ErdWCTVeatVH0*Uy|(-}8T?uT zD98)~I(K#+$f#nL5l9l`f?Luavsx1U%n&2#4q% z)t_6H`d8uuso(?KpL`9%9cdAF*lS&KApv2&k%aL2e4vg zCl;^l!e@(C;iJVXFn>iiItSCp8Tse`(OJO(zc~=+pMMq-p*W)9m_WF^*VH$VaEszr zf(I)*eK4QKK8GBNmp)qw&w3jo(9{a=-1jl?;?tuB05osR&Fi-#^0yS^5lH(x^Lqt~#-mK)>#J8nWvB7oOknu7y=c`Sw~wqt^eNH~aRXWfP^ zciaRnPXsPcy%}?5%1Y(BXk{Ol*UC5^4N#5rvN*MZ1U_(iMFzERFohrQwk=+NUI-%j z001BWNklr?pJH$vlar{Lxj4#ggUg5dyoR5i`*!IfA36=$4!ifq)@raHXx+3(xt_i2hxQmZvhK0 zJsLw_d?a6iu=MP|{{cI1w-NF^Lt?DG0d?xhY!1IU^^Z8~=zTH1DIr=P%)Xga5CjOs z{fM@N;FR>7(@(Q3?b9ggYG5E(X*-(=_+(!m{~FZDCe2xqu9`0>+xdUPy{m~32YFHVT{+0I-Vb% z8(9Mi4r#Dy)hR7`TehGT9T-v8q`hN{rD`r|uqh79iv6%mYr0lS91-nuqu1?VQ6Y^v zz1?^_)sGdqqM0eV<|_H4QPhlWNBx9$1Ya7}RoVBTE56FNhjYs@WC*DlOS&LaVvNYKQ&b0tKVJcC7(` zDOnA#0vHPWwXZ(xM1w(5Fk|$}Or4@UV!-8yQs5_o!GWX@1xdE+?C3XHXpGYX2l@vE&bPy1s=ENl4PbCW zE&~5#`GKFO1Vd%6ioBzBl~$NXY&qK%3-SPZK!v|KELnKnj>yBxq&o4$%J`Rhq)E2P ziq-_HBKl);E&T)=)tc_0a!-G`nx#|js);M|no(Gq>b$G6db9T=3#?QiG&-mv!jzFP z8+h33GSdY4T#r&?m9XfrJuZlk-~AX@TzoY?cvCa2Z~LIrpE0c+yYI9ScHLY5wiWvV9EY$QijeMQSBGK-zm**siSh|7}&UWAJ<8HHmwxP^zjm&;WjP$V|Mud}lKS^(4=Vt~_p^VOdUstju;>18 zg?uRddlpJ77h&dMKgVA#ItN~lgTGyQ4bH#xx?xUXlj)Q3!qaylTpNZr+ys}qhHCj` zW3}diuQDUmdIn{jN~f5~ZsXd!-T3s2udwG1n_@*r62VP>0q-yO$CZcw2#3YI@Nm+c zTMb-y-ypuf(~kJ$W1X(J(FRlS+_U$fHUYTvDY#r&AlQoMUicKd?Ril7d(=#yj?fAJ zK#vnb$jPce5aDxy|BbSq%ZnC&0rM|90;w-QllSLQeEN#BvD;3YA>T)x1zrci0uKg; zhH&xUZp5ia?290Z0?ksihYp&h!(dGS(MBd3!zb=Z_k(R~8&Ny6JThbS)K(I*m!N`s z)kyLRq7}lbMg3U(Wfxqou-XHjG45%%7cQToZA2RRD^eebBnSdfQ-jO@JsWr4KkGXN z0QRmMa^r|iSg|B5?|4zS&IC-Hu_3&%h&ZL7+Xp9;N3yRMJu6nBXVq#9ba$gbg!EfF zCf*xArJg-*ObdrGB@n}ua2PGV0BT(xL>w=CV@tWOkkIIGklH*ITA&U*p>t+h7_n+Qvr>x z0;U842nlJ{^1rIyaYW+w-#UJ~Kdlic+kmh0{^jDaZ0hn|mTh~}YmYctX6BKwI8v4X zm}&FBo}OOO{T~`iqOPt^oIMkya7Z(AmIz|87`i*V1(v7t@9pVDU0toT=8@<}k{?S1 zRClB9e}CVA1O&qTr|fVtrDVcTP$hreEG6i*kPl#CcAZYAL>&eMJYfR+dp*(?$kCw# z$w5I7RO!ki2t*+0la2%~G*Jh?nJ7p@VkZk)BtYTxifE76$?}qw!wX$N(-K&T?kv&I zj3^eTSjjA`X21Q35(S5SfPPoQ&@Phz%LqUj9;lQIZ0fIA6>M*+rLQ*&;Hnzb5N9*TJ`KX^3F2oi@iodu@kpw%Y`e)<(d~E(}%HQj(C-I3SCj zhzlcX1_JUN6EGF>DCP3T@vGW452M`EA_D{l1!RdE)PV6$+Cj26jW6de#hddM;-$HZ z@Y=#9SlXSea1KlW_swB}e&4o9V{z8$r(^$v4nmYhL11YSG&Xxp$#LA9%X_=A=g$wp zyrd7It+qmNLObxm+vvILPM}yZm}~oNyTW2H8{6Rg^Z>YWeaOsu6u!ZJoOSkTIO(_} zkj*CXyW>yCgOAJ}c3);5_#@nO{e>vHO7O)d!*PYAcCSa+nvRk8akxpTz~9xcG35id z7f;Q86$kCL1Cq45d;T8y{x;ZekIiuPx@~CYkQ6tGy?)$w+g&)~@L!g{YFkqSUY&g# zCa&9zVyX`wcN&O{#h?Fl7tTEIuM+-HC@D6k8PVV0g#Ks?!iB6b%*~Yg@`z}1F`AIZ z{0n}K?DB=>0N{zsPR5?QY>j+B2Zd26O#fW9crk8!;87g^>wS>V49WX3``5O{5~7U} z1mh$ysv4h=g{#)ATw;+WQDX0~hbfzBuwc0Xw$+jhc>*Y5bgvl1!q2+s*5P#rB;zL% zLB&xaCDIUyet~FJ>*Ufz99PYL5jWjUg6h|t!L@E^7d(ESIQK$&_}CizlHs9&3*q`2 zOxk#3)V8$9^@v2Z*CVJY9dm)@xXvDQcXXn^rxOEx{U~HPBjTG+mGGQQxqyY)8n*{c z{vcX?A+!XkHQ+(m?ICLdF|QXv>d6RX&LF}ggQEf*4(am9KsZ0`qSuSG43=^u<&@Ct zl<;|a5T9iS@o{PZ%hGA2M;Rn&uQps?i>ArbP&2Vz)=Egv+$FY)%ODiISCq9cbob%2 zm**he+cP2v(6UXd+k*pZ+c3o&lT2R-engzjmQeJDsb-^(qj==ZLPq)%iEWTll_KH7lJ;A)bf{X-6~CfV_t7dBVo`xW(zS zPER2qoiU*O{yao>959``Z3*OIBVjQX38TBG2Wd_fG}GvmfTz(Wy8@J)qj0DY5M_pT zg(It|0Hec-ct^F=rIrFJrbL4|H4OYL9l)w=W6cVNL-_i0Go#sL^EzihQ+*pG*qdAa zG^;aEB{^wg5LF?wHDfd0vdm48157>g0G@gB8C-F}-_X6h`)f|MPLAUjYO0IkSNraS znZNh}rmjC7-l)nw%hj@WE@s4Un8h@-TnFu9(2Y(3n2fZ5srX9?4ub$$bILli6jM}4 zn0?}m%nL*+2sZNH1(euT!o@8VMYLyVU;vAkEXF$@&BJ4_&BL6}S7LR_IO1<*OZ7=U zzX$vO;vgJ%{BfAE!3HwmMnqv`vL&ZpxO)UgVC?tdu0bSDtqbw|V}wj;4}3BJ7G zkI1LKrc=TOW>tFS!S;zL?t1{7C5w=I@<~L!MO<~|AFrl>wMv^9s(3V92Y!F~Ila*G(6w(ckKY)&}2C!&8&s0QVev;BeR@;<0IrWeP zV?hJ}Z!CrzUwRc+-+u2m1OQd-s8!*fE{+G$))sifVe~Cs4rJKiHvFNktKz|_iPAiI z8rr8%1x4GatjO=kbu~R1dcKPs@|KarEZNtG{@xx8^z@>b%}V>U1aPKXYR%8opV**) z7J}0qeVn&Ybb%-$N6!b@vEaB-7YSorJcb63AHI?sJ}Cthk@x%14;KaoQs~Jhu_WDt z<+%*{iv=^^VRRD~sZC()^yx^9X@wIA&;m)v7kNFE>rw~KjuGBR?iaSA76u0J=?gC* z+sjWLzII%vZKGlA8yX9Li9$ebl-QMGkO?C~A`?NSDo%xElz zGOSLen6JvEVVvIT>?hYg#B6bCjn8W4zgsCPM1{!GugCg4zSHoUPFk9M$^N20*;6a zG2>^@B5g997H9^jRAjF#6lGKZO=eKZvnsX2Dk5t6?uqyVH+ngvn>Ir8ldu! zZTUf+xke27-q!W6nVA?{t~T8cfH4;&#)&nwvQi=t_DAvjbFbp!v;TnZWi(XPAxzcw z(TO^!i3D)qZrkIiBY%P!o2?6Xh@=+>jyEXvPZu*q7s;LMiw?kXE78*qQPJ_jynb>* z2$K^DAR@qfPB~W=B=d05X|NQ)cDh1VTd@iboIE4byg<~YoIzDeIc;StWyn^Mp)}cn zEEayT6p#PseLVQur}$_^2Shr*3cVQJOjLf_);53{5>QlwV~C?;-lkFMXtNc1UsXDim#>y0l$M}2Mr1k*=S1?ey}@S z|9Kth*Iq?i!jHS}yBV8pIvsDn`vLYl=t%TY{m-Obp^z6ZJ$yAb-FiA4cNCuZdT_|r zDF>aZJ}39Hyh%r7|HB-Irc7dZj1Gk3_TqvIFUCdZp9@#(6gY=m3N%Kj=_@R}=GIp1 z-R8l6E;tjPKmF7QH^fl4gdgs;8TR|}uITORz_m9&f%yx2%)Zw096KSJ&$<=e4ddZw z0>KiHhX|e$y?o4=T^=-LI`H8+hoRKhBMVA~z%y5!gI#vm0=ZsFkUMbv0eHhPeEj?i zSh;FBw*B75(n`!gMn>z31uCJoy%rw7Y00x=s>{JpHF9F_ojt3=rN$*@FzA7lK9n?;qh`!~^F}P?sN`vg;8ND=M-#d_qWBjz~Xc|9O>?*$# zgK#_4OG0F$iy`vbLbfKAhlyZTMy==4X=Ekg%ORJ_Ae+k~pW!?Rc6#Lnz2$@7o9iGp znLRfw`3C$55JBW;aKM|-Ct1G)anh|pd*gvad!EfB-QS6>rAvirzc#lQuB}Dew5dpp z9RrscBQM`WI9tYUn{o^j3Yp$$l0AsSd=lfD6koK+3U6fKlpjeQZC87;bw)^&8R=o7L09(GvoT*Q+&ss|W zV4qP&nE&zeLylx=9=Aa2B;Rq&FNskk&5;*ChtG_UtbWS<*4NjG8X(_<**78nkSQAw z;-_}|;NXyC@~pLTun=bf&`A#t3`)(Pj-6!(b`8*R^LK0oWZ=LWKYz~bUjhM>@$=u3 z!O6@4jum#xe{}4u@l%I@&tZfb^aat@+>Ea7E+o@KQjcNQ&%H)M2^9~8^=}YBTkTi$ zPH(CuPYrjvW^0(!Sb_ExX%H@fxe4-b^Y^l}u*p=_(Nyk|O&Tj%zqwT-QHPP+puBSo zf*|j&n?4u}W9|oYapnnUWAOqjE;I5Cw3C4V>i1@h!#StT#P&PvfIy8Gg?t9o=~p?7 z2;i@U+Z&Y(L@V6f*fRCPFwz-Bso0CHL9i|+hEuLdkpe{-$TFuxpy41=kki3GBzdNj zaI!2DcoiX#VM1nhx~Q;mmV|!sQl^CNRjcvxocD3ZGjHS7FP5P%qa&lg&4ZxNPP^=k z(|&(CcHI7ZWi1S%OskSf?0(>{@CCw%?!Gf(*#72kLAr;jYJ!@%UI%4J_xbu#G!oBWxzyW8Y z6f>%uT;EI&``@}WK^+f|{JL@*|woQdEPo#juQ#2#vWI)!E zeck}-dcML3=Nu{bo)7jqyl~wG_}(@fA>XgbMbYJfKURb1?|l%7m=BYujzdly1J(G< zENu@^H>L(|1^|LcRXKu@UUYh_W;1cx9E%SO=k|P8S_#=;bidK(lxVRX#@0s{-bLaB#=ensnUjbzf}LEV@(v`?OjctagLU1y}p2OJeBGg6im`OIkk?C&hlsunz5xPz?%AP$YEZcXt#0(}0D1F?IqK3}Le9 zmjF~zGwT(?cAOO{}Rk>bEvKAA|86k%5RW^@iF~u>{ z2$UF%x{+MI5}&>JvI>e-KR6cHnep#6*cyqFf5=1^j3y z1Y*@)%!kVf8R4nd2mp+q_+}ec$?L24uem+tm#_JDrVa4sHy(FL0HJeaMo#BUSSX!g zwjDq=n*k93LbuA8cZpOivv5lOGH9R^CUh?>PdRWUnO$ycT(-}hucz}S;gEzpe?Z3o zvqZoMjF~zg+67P)(i*h`@_Cj3G&{Ea`gZ0#qdb-pq`lCvdKt7RX-He39LhIITarTD zEIU{=JmJaNtX;AxTg$ggW?_5XRJK=N2_X8unt2;xm2ww={!Z$FWj%76eQ8ZfBS-rl z`uzloHW`{;ftC}>oPnwxAwTE;1W(s@vd{H^n@1E-&GDn5Rn#Huy7fb`IoN{IPA zIPSomal)|&p=s(w6xb0V4x11^8U0bXf=vLK=prVn@F9(iZd^I-`aPxh+6cVJlT?gF z{*>lf21@G0%>t-XlX1X={_}9CKc60gi}m?jN>PG5NrZeGWsj3%;DCICqA1M4<43wD zix1xY47dLK6+HUhd~_!1IKEw}wYH%SM;tyAzx~Z`Fk#|Yfv5*^1?+vuZ}C=t8j(G} zkMOt##GB$M%y|n7&$}Ehhl-M;KY}$;g!~Q$I)>mLI}YJvjzQ^*FOafT@5E@Ru z27PTCz+cS4;Z3A~4tEyq0X5ZwVMLdFgb)AlJGu9KuvYxaO&4K{jn_pXNpUh4*#F~= z)Zoz@Zo_7qPC+#0SNT=OhfE4s%JDj=A6o;LO9gBsaI7N#Rr`E3ox`u+B5;;0SPh$M zGD+OSx<2lA_WF6@xWia5cP08(r+m7`#E2&m3?xfj1b$GxNW~Syx{tB~-o0 zHFuG{Dt}`mLbY}1|8l-K*flX8z#EC8Vbje~H)UOdz5sonFF>kO1A%fvGU5*U zf+4g_8iz6CCm+!W$!*Z;F&$;K=E^0euOg*KFylg&!&oTQ_fh=pw3@#xW6aoz> zlf@97bxb^GwG=QkIDn2NOEIvz1DT*qY;=uOj`$Sgb@QMD^F?Md!qe?G_a()lto;>NXEJc)ZUw8uDUas@~llUuwsJ6<5(; zyO2xfaqcM>;loe3HwSgWK~5~vBpYL)7=WsT(lW`!=6 zhB7I*(>au~?6=Y;YgrF=8Azt4>(6-+@4WXVZh!1m%zEt;baGmuT;tl@b!BBX-gqON ze(K5CXWzY%bGvZJ(Wm3dj}{~Tvme4Yu^FzYA7dN`9~^TU+{+e@Fi({`79}z@z7B=9 zamdct7~vV~qjdYd7<}^`$yldMo`M&jxeH!*4kw>>A?|sI+5(m9IN--S;m+&N6yjTC z%!VkTNm~HR64XXU+k9lTV;gq(s{;T5YRmvExX?K`h~2i@0v~@qAO0U7jofzo>R3On ztuG)%N6$^?qO{<>uK}vpZmD=pfq)lHXI+JXNn665$)H%uONWsZFG$vPJE&(%=7%ri zlgm#n*O#L{ALiU~88)0Y0fiwF5le79e&n(ap1u14?6B)*$maNdjyQiA1Xd~`kno|V zB_hLZgcN96cSn_f9kv~+ND{*W16^6&X;m*M2k#p2Qa-p;3gGkimtkn20FNgmXGH4d zq5;4z6BoSxAl_KE3a9+-??@A2F=uA9RkWF6Wb$-)f)Vt8`mP{idOekgT%pT_=;Z0B z+hkJ&qcP-%Qpk6&M9+e+Fht2_qA%uA(el$D1Y$9?PFe>o?d^i(^8OUeR73e3GY^I% zjfF64I-GQvlnI8+U^c0T%bF{~s@f{%nw5s`<_RHB?toDu6g-sXki1IXAC?yK8MLE_X%x*P zdTnMbm~cq%V-*U#_LKB=zp>t=63z~L_8Nvke{0f3xc)l(UWddC8X9KO%;u9uTbqM> zNFW>N>6dN*w$=3a_lfdfPj{bW@O1wDy#pX`fG~b=D*<} zHIxy1ZqgI3gA#O#gr%t+jPnzIv5J zS<+MLfdm$H(He9QbPJQ3BtS7fJczQdwO3O!ZmYCsf+3T2%Z4}bm7X(`GZ>Gn4%;3I zb!zUCnR#xI1sM^lh@k`u1~^lnB-xfd(&lEG&(_mYxr61u*-c~qB)e5NlV)#zcLaa` z%k{YRAGcItO;sktIREy#1g<^z*Vy}KJEQ0?$>AvY>f!d)!X04S83)e<;kfc}IT>}L zptI$!w<1VNeXQ-cP&mI)5ZxE-m~AZ8wUI$n8|8Al~oJNc;naQVeY$t2BC z>-unc$Eb9%tQ`#+cW~8Xc+aSD5miBtDIKW6(f^jLUWGlj-U?r=ScSmBXCb@6P7s)d zWfleigWd34a|%jbOTJS8AkM|>M#IS$ATwikIGLRE@e2%W;z)jrmS_~Y7w*SrH(pl$ zLUo}4-n{2;SZ91IibGi~EqQ~|y7umibFj_!8zYs?$nYv=i3Q0niwM^S5O1WdA|k08 z20C<0Gr!?Ek~tIQAgQvRc1K!6S$4bSm{lE|McgC+_WF?>aACnGE0D=iV}kq`W`(-{ zc~bm=AU^Kw!7+ci5(AVlHYDZI_M_MpQKa;tWz#JM;pq6_eYlH?JgpG~&{o#eqIvpe z2#p`B+6c68{k=%7Sb?s^i!jvJD{89tVRszuXr!(d^(`%^ZEArh6oQvRUb5dR0p>z3iWcvD1l2Xo^4|gDlmUSkf zb?OuZ5;1|;Ro{uhh^&sp95UYBw!9d7BLk3F@}($&EoD#u&H<9EyT@O+`2YYQ07*na zRIy^=LbOgAk3@5`P7zdPDnX4r`2rTa_6E8Zsx-BI(CY0NO5n$_b}3~PNcJ>-!Rp9R z=fY0gEEUpN*YC$fz9)SUDFVi)h-|RoTa5bUzww8oCp3CbZI)=>WVkD-ga8}|>~nL- z4#{yGxWkN`U%zCjUCAcW7K$-yg_WDC7`wQ{2*uP^uodY$7v4)%uAt{B9Oi&n ztLJOz{H6ci=%-8OYXSioS!{@V9J?!LNu1SiK7fQ2#$bqnM87v(QPkPBgZ*LDCc=kP9|L7a|Xi0}9bdP$xbnmEm z()ah?13x_S7dZF4n^2gsKEgYF54n&ZCGEnmSfmMs( zx%PAvhrX_JoT>xg{RPI}cum zF^zE)l9X31!4nAK<5%AhiQ6gD#$hO}q)i%NABTJubEs*HArK?EP2pyXY^vx_*^QUi zdU%3VWhI9#UnMYGBP2J0muzhjBMM?*bp{K*=z>!siP$>Z~)6^)0XU~~X%9vl; z1Np+beo`P2Sl9ID8%7P0K@k@+&-+*Yi?YNx9_us9wQ$yS>;h1&EdvUrx*A`-Hu)q{|{*=*|Yv~FlmtHSpD znQl_u&y{?m>Lbi+4I$CM-Fgj`i?BpPeiw2!I#=}I#3N6`ypQLZiBGm}STSPpfEQPs z`g6>j`D2uvG#qaTrC>Asv1Yh}H3EXk$wTfd<&3c6td4PHNm9a^o6_InM_*8!nO37ZhGDC1> z$Sq*aQ)O7;&cov>z>N%?k{4fn*@3@4@E`p1KkuS%XoN^i)s5DvjmrA28QY9l`*?JW znF8W`OyB+JBm8jN@1e`>h4;6Yq0qXHkTPY>IV;rOa94){d4C0kXAH(E{+`Ff#&Baf zis>wW6T8;(XO-O@Mm96qfZG*7cUK+@KktC66oA+5Gw7poV^)`dW3TudmMmXsXiIAg z0Mr`jX>m~Uhf%l1#)#I{VddNJBfm;pCfD|AcOZiB*s*AuunvMPO+xyl!;Ub5D{Q!myvNdepZznh3jN8XC_gFf(Q!@ z_79-1w+HXc{*bZPTVB(%c}hKF7E7`*Xk0*3*7S8QFYy zZA&zpNt7lf;BB{2M2~^*bfK%aAS}QAV$^<`=LYU z;b6Cb@C;ZIFtsEi1$6F$Ja9@?P+JM}g`yBZs8AS-h6JThP5{Ym1!3q)ZP3(!NH}Ck zgTaXas7?u4q6#7oMCY${MB9=laK0#i8B&|&N|@myveafx1wImy4MQX}lh(>Xf(;wW z_u7i*sGC$|!9>j#TC}9Yvd`C>Yl%t~VxUgHW_jb9OK-sK*WaykE6ow9l)qJ+;>1IK zgiFpk6fO+G@di-xH^5sn5$qx1D`5(y?*@dic4|S@iQ^&!F%z` znI~Z=B@9PdUplutuQ(C=?z26L{u=ljH$$nUvc=^ofVKs6r1c+>778b0SQKj{aNTaa z`{BFTZS!r>AFYAwn9JeRw+o*_3!x#nKX?VW^J0`36nw`=h=kmI4n}B#gf_)_T%??yg1=+e-{`939*%GTci4O6C}Z~i>=e)2g` zsMPmIy-jXEBCXA+oiGuxwq|&PVa_s^{YJ!;Hm_7veHXIdrB#=!Pl?2^`&)&N5-7 z@R3(%u@D8YM93-)b>SI^y;c1dv0BD<>%BFZw!o&^j+ajjVg4&~knLvcq|w2NN71t0 zbTmww2$w;m=_firn~#OBzdr0M&=T%d+l+0(4Kjf+NAz0cp9xl3#Z3?LE;qV!L-6E= zuxm{nS`3G(8aXW=+5egk@O6RXC@WrN8_I3x*S!3Y<2Usj_HSx?9wm88Qh%faj3*K@ z4Um~V>+lQ!=zv+T7uLFAlS@8WEQ-Tt2|)VMT}tMoQDX@}04gKGql0`LAqz%hI$((9 z0zO|g|CK<(fPixXxY>B$Wd?!F5zq{R?-z@NB*Q4kOaiSL$HO7`0v@EYd1MPk`5oU& z_D(?wf^;Dg9U4-gz)EE7dO77u>y;V^XbViGW5DVHR1PT*ghcC_sG3@>VOyFO80*1B z;HK=NtKYZk{mSTo`I+(LmF@%6bL@f0HGlBV$2j5FC!?>kTFj!_h&kA5y$QJI>NC;a z7Dh3b2I8&oHLL?yfX<(#A9dIs;@lMFp=_&hpz`fxlhU!1+{f!O69)Czm08V(a#I!Y zGt*bYthF)&(N-B{g=s69tT-=e+|Zq?Q`;;7(LjJSOI}J0mw;3j#hxypzXzUTTI;X8 z<|2_TmX8YXxtN6pv1rKvuDa(b-1_{x7|5)R;m)tivO)sc@(FeB!vVc=4rYFn(e??!V`D%slKAWO9}O z=|Ujr#jNYkz#e;Sjhs6UZ~aE9yI?XwO=~Mc!=oA3%3ZI{h05(UUtx+8YTW+|YtZQv;%jI(UiRdVI<$A(U;prx-Ykb_Y9gc;@m2HWt8XJ-0w7*goi(h#Y zg9|DFs+?n=ABQ$hK&|7G7DUd=5K_5tl8PcI$A2fCBDypESl1W8cHuB6QN#eHx{X(^ z)?9xjXVT|UUo{@}9Zsgg$oju)|MRdD2?mt|z>Jua0Yln{9}FvLZ=kmyi9|v~ zdTMIo=Q!uEfyBCRs3I|aKpti0?CjGG;P+m(i zAbY^6_bh@!TGOT;0JCRj zTXPggD#?G+Awcyh^CCjNc7PG#FDV%rCacuCOl`?#_4I&RZm=bRN>)&PuvG)VEV*fC zv{1hIyfOhP*e%HRAiB>S`>>eoPX9ucuLsh3e#82n{Jr8L>PBnehPNo zW||QDypcLMu~xX_W8k;~MpckYqSMt>v{OYq)HhT4Q8$ka{@@@cw)UCwgtj)?wj+MN zayDrAD(!2=(Us4qjnGYvR{m*8N2UZIEsm-kV1tNCEk;yfnBLP$OOFqS|5%rIv2aYy|cSN#1-xuk#IaR&}R;$+$9)@X&p z0X%W@IoN*385k;r5NX>AE{*}V4yQ~b)q7zd)+~(t78YT$hePhA+kTr0R5~6-D z67%NZgGSe2y7OEbfa!Iwe0A% zmaWY@K}6IagxlxSsjH?$#K4NdHp{PazSy2y%8NQ@^~Kt@KFCktxZv#eKjM}+y(w9O<-+SYTHh+XsxW>$mP2va^- zJ@*T&c%QQ^D!e4Sc5JO|o;nQ;8%{$h96+|a9}AwIjiMQK&5vhl^wat#Y#nJqDOb>z zR0dHdN%9nxQ^pB`9k~>W=>hztz7cK0HB*grf#q%RS#_E#xSib@dhgeE#{cU(VY<~^ z*S`F)Q!;&&Wb$(p^!4=%v!08{tY3wCI4~$BZ6YG$Nm3t61#Xu}0S^oeqOP_^9CuGw zHxe~9l5GzT4xqNC7Ja<~0^Reu$s}hAxMjj1y9N9{zqAfg<&O@P$N-h6EZL3_m6u9U zawxSvLxU;fTTN{vTgbvoxnP0dRIGwd${!4gGL`7YXgVoV;5jOoge11&__M_GirJOm?jL}=cR7&i69|@N zp;9&vubTuz8U|id3?I#1fpczn6wkc-skZQpJWXX4FQDWPz`w!9i0r;AQo#rcUN8Ki zfV2P+F)Dci0T|u;UHSML#(b z4dUOoorSHo-2kaV1ktuF;r4KTh6xTeT`)V({>|% zhsq;fUym_Y+>B+Rv2bV7k{Nj=1kkpr_ILov`)|Pfhi)rRkFz`ou@ z0M!Nm%95JTux8pwXbS>H^P@sX3{gBJ8|Q!UE#i@wi3L$;%1t-OHI@8tgnKV?GK*ns8<6VOTy2NTE= z1Hyt%6Lfn-VNVr9b$}a7W&V&`q_A~Dpq_EDNeV<-&Ywz)3#rbGZ#KFpDiN*cMSo9@ z4bPDW*{(i({+~I>50QUUK^`ls;YP5r0b@2;4>jY*p=bW*STyI&VQV`%;KRX9QxKzK zBljfrDva6X_mY6h<3@j}fR%$C*en>t*0DPHWm2W-B#~QMaqSiX7-@;BPWX2V1ghV_ zA^wFqgFLNpLJB0UgvsW9jpIh2UX_0rB(6CE&!t9OWhRd=FLnV@u)y+Y=qPXt}F1 z^@%hkVg5jb!z6UnX`Y!WRmfOsu*zw&$w&rNmz;Mvu2|d0L?=K7dB~t^GsB+Bf;yU5 zZmr<~R22OzFsSCn8duc-sG1L82!)!U+Ll5)Yup3})pEh*_}!oeX7lP`6V(#X4gehr zLy2Q|(T%fD`~#kO^4UtjQQpOxovb^x6%YRPWK16)WeA00xCQP6r(`t?+^Y_kHD-^p z=Y`DA06?|-9VaIvMZq>ZDtNIKDaY}yIm@8bLnd7zL|S}QJrSsxj9&FTyeI|+N;H+j zUQS>YILbb8x^J(B&x?<*I;8!DbL;R=Ivl_)^OQeO+>(ju4(+5SR zOoFN+T)rSy3<7_>;}P8Q$mdn-vZbO1uY%I}FtM!x zjSD`;yZ^WzNv3}0!5LP6`qP;>;rLS|7WH_2c;NmA@$-X^L`l4?9{pG}h-Yp;1DkC# z1F2jDvG&aYceLEnshuDO{Mr zKmq^`M{-M7i0h3P;koAzGW2A$$AzaJgOkrc3z0}I26~e?^`w(<)1CJWduliyMe}9X zqNi@Es5}ySWtWU!q+eZ_6e(fBpH4&9`)`zAM<;pLACAM%_xl0znL+s6J}m!y0hTRZ zj)~)&1SM3GCpkWx8&ZTP zK0ql2i@Diys?k)i4xeQ~lF0cX93mwzrSB0x zrMhG*KKTr*=Ta!m!a>!4Rg2>B1W-G966(e_VaZz`A~QhVfIdPl;AahEv1zCVg&fr? znKx;2=eq5`H> zF`pn)1c=yq2nJ7ln7DbyH{NOQM7bL9L@XNviq#yj!f z%m!JGuNV>%mVMYZ$fZ#k+78#$xJb5YdxT@9MYuU7Ajlm*iU{GicRhjcU4J*Wq^9(N z&&bZqY&MUuU;!e>z6Yg_9_0OD_&qKxZB3$e+iQ60imQ;FNHu-@?0-8AKlsCS+gHSP1w1`Wra#&;wAY`4H(|ftric8Oj5oKqt*I8zJeoQqmL? zIOnfF*n&76(;au-fz#f93Tkur2F|$zwJ`Un34VM*xL$e=-s>(<#=2=QKH{5xb}>#l z^D|NmtyWz4*?;~RU;5g2o8B2}O(OZjt1zDE7x`5_Gk=Y9Ib17#^p}S4(s`dkew+%G z`icYsc<9=TaL_@^P%Y+BEf(?8BTowLcpyYTotD}e1hW-Ldme3#AlVsqT3HN)sksu|g>8YTjJ4(#+PwH70w>pHiVIZt>~CL2l38!W$lyLnK&;u^5c_u?V-m|&P?O~ zw~xKyUIoHo`40NVM#HdgIF65W_QPAOq3mK1P-kYP|6)ammor>0V0~r~?~EjIL^vXI zRARlHMQ7HFEk2oZa8}!F&VH8xK>aB-HxTT-cfob}-*2r2{XQwhN8=plt06U+GAw+Y z3<#r8EWzjT30og2e6>t%q+Z=FdC$Y` z1og4HkV{jFSc3qz2I%yKmbk$7f|kq~Ez(G{yB7@ykSkPB5+n#8F&9-4K7R$J0xv8i zkz|05o|}@B3t65wvt0hJf*`?vE&?$~a6>FW*l3C?pv}(es}?v*PF4B5l<%eA%=Kd; zYexBIK`IBJ-kZj9y|Fb8ov~&a%1))Ja6Ot8yJ+V7?b;BjQ-fxeNdYq*K?BDA*=0Yx z62HEhGt`Y9tN!p0J76(xx#VngwtFSB^RV>aJ`eEm87YstWZdR_#86g9$2$dAH4T(= zsH8?w%%xGyGwUahKc^`xyF6D>)}uzc51vp2h_t~SjFZ05bbL znK=LU%dg?hhaZ4K*@H;$3b?%8PTpx9ix^PjzybJOz^&K)5GQ`@ER<{H>!{&7Up^lfU-65k zQwcAeht}_0g)v_Xd{wOg_$n^=sAw0B!@ufYto`AIs8ATnyymyJUT#3!Zn#R*~ zZ8Y^^tx=xg@wEL_55%lH)?rtN>z{$RJBrkB73+ucxaQsmas4fKHJEt)(Uyhx)F0c& zFSGadXdXX2y`4xbSOkvMWp`{tddqfTl7Ya??(&{~*UsMO4hP|n#t`r7L`!!M+B-Yp z_6Ni;`E1FFW27zTs9;e70tUXGfa)di_a!soW1o+p<<%(bGcmLOmRv~gF)4o; z6G~Md64N%3#+t_;lj(-;<$I%L{ya%E`CS4C2Qa>21J*zKtO8(n^RoM`ZjXSd z2l&*SCFrXKQRaG-$%)2n-X+zBf~SU+6I;;%H_q(nL6X;ESPX5zqcSx0Fx0`XOgpcg z2C6$b|GFhIKUrMbFIN6RcmN2JLZ z;swb2&yhch2r<&5b0?7sd)zb(#0{{-sUv|_0@$nb{vwE>Qowu<$%R4$`4kE$mPo0o zDt0+Aq8QHT7+rc6`A*@0$?y4M><1}fGRv*z~sY)Mge6tB07>U;V zPRc7_^K~8lb9&mQ2gE~JtbvVUjRi6|2r&)XK56(qRx<_%M{w4^o{J5yZfZ6rrhM*k zSMk%YeFSHpayTlb99*$(xZC!Ei!=Y;fR@6A0$G}DvN2sKpjwy&iW!tsqbN*Hz+GfO zMl41{kYR!mZfe_Kll~;BPvw28(=O3Dg96fcQ9B|Sf-4e-JK72aB5?5^VNFv}4h8_4 zNm(bY64l~NO{VV<4ViMkigWTd@j3DP%s88nfT$pmJC{Lq$5zx*V{nm@mQ@H&IWX%L z@D?EuMDNG&{F<#e?~)tv*t!8zfoZV(b`M$i-r0&p?>QWyi4knL_gQ3e!W7_SqaS+T zyK%*pKS4`p0+lM63PXar_WJzz+r1Cs#1lU3=wR>?!XY32a{X8FmbV>()KmeS#>ej7gWfe*s9UAzW{7}Wmd}L4L&KnA!&k4q4Y&M-ya)9_-RyFckNmZzv?KLx_pYD0wlF|F4akR{tgJ^3Ufp`KQj?K~T z(y7TD_G7~AdgCQ(AXg>s^ig9U}UN%nD0_CjAqG~Zn za%U*%6B^e$V9Ks>6tGQ^4%b6ETEQ^;-G zK6}w`7Ux^PPnv?9(AJB$#=C{Ig%VoZTaY5XW3`5OJc^022}C0iVgAcZWsq!1 zBFlwPEXnT~1@a&MEM!E6`A--D$@|VxKlT91MT7$$^!IjS^LQGmsk}HOg1k9z90+(& zpyoifAR9d7ccZgCfvKq+Mp9`ZvS2_#)j76l$V1Mx%2`uO=SWRzUOz`1iBBLlKv1Rh zO`KF9OO#FNt>YHMs#!eS=N31hL4qmqoA_LB>$E7$P!a3HGuu~6{dMyoB}_5iTC!xo z#K7t=ci)R|U+{gIv2LnY8<5@7c^&xERbRopF0vqcQHyoM+r1REKnpxF_NPXfC|{QJ z-PIf_`7ujp;f`HODAL#sDRi>RrdZ~oijzkNOzY9$U) z*0(J&hG%}_RQ&LV7b4ygmI@j{wZsX~8F;*5-2eASapHSFh+M7?6ePFC?N^_NW8eEu zWHNb#+vdR?U1GQZOu^d9+{(SL2bFpS1}9-o#kQ~HZ$dq)RKmZ%^>%#Z)DHmj_J#X1 z7o(DhD?1~ffr#1o;koMyc>a1L>St%yDC=)E?6;^N%lBT4hn{>2TZWinHs=~0XPyHb z^&zD51yy^bOfLNJc>U-oXR-AgpG10lGu809#~+EG{^%@tTwY`br|`sQAl?PQczNSwl{IDLLpXO60psImnt ztxqOxWU0+&@%rOWBfp)*NiKxC+tIUPU&OjPRosb{f{}5oeehvavkcI8e@CXjXIUtW zGy0anMFBE{7qj&Q(bu9)bi1&zn#H|?8*xIS6(37>!NdC|WJn^0C3G?f2jE>gP6`BB;Y=Zb-3a4dZZP=em>Fu1UV7dN9V@OpS^koNVtV_ ze|TsZ$wVCfU;x8|!y*~X2f$+_;ygxPKzV$C!WbwHJ1C5PGV;eoB%_0501OJ&fG=VD zV>DGFs~ZsXxzN*<#Nb2**=$iVVgib)r2eaAcRKPWEKMYlisZ50WdSevZn2rpz@#B zqc104GpzyphzwxKDeu}*Ki$@KKqAT7eE7k?{|9dU@7o(ztPL*o{pX+dFZli!Plk*0 z@7_4v9Sh-Zn~$11q z&h90@H)$v{AH(3KWE~z+@M7gb2%6|6IfopM!<}e@JJt%9pJFaro)cy|>8V=20gHt* zlCm0MNj9j@qaNMr)P}YzswMthLN%WPvXhKnQO!-ER^;<$X_9l>WD-C!p)%%?t%)6X~^u>@5$r%1FaqAto^t^vTKE1$u! z$DAZpEBoSX{B75qj}zW^jG*dWz8C^s2cueJ)y!s>jYhlCS~P5RhY`)HP}<;)0htef z_|rZ3zxV;q&X8m~om#)H-&%Zir$zK4+te%>-&>M5l#>6xP zBF@bvJ|`STuxk#&t*rQb-RMhZtoJ=}jLlBRaG*#ntd1mgMcM;+9Bivt@?KL7tWns~768Z|x$@yVYPAv(`J4hM%LpDXh`l;e{IcAiOe8UxniAUHXe5l`kx`ilp!4Nu zAb;=W%@%22x3KTYNg5?6I(wG)iRx!XAU%~)i~&pP%!J%Z62uAtXHHc=pe)B@;K51( zu?I5RS1w8ao}AUy61e~r809A@5X1)XdtLC#n4AJVXkd7L>`BW=ka65rmq4ZxjB~T9 zf;?9`SpL3Daw6d&(B8l9WG!P_JcRV-*~*aek11C>cmiv98p%YggKU%=u0J{_7&cL` zg7TE6SSy)sVMhD>znzDdo_TqesMUpzLu236%-HU-}n*>U#O;FX$ ztdv19HH6Z{AYA18M&q)?syUOdl0zoQl$TMv%)fFSQq<+^~#404_b~s7J*NH1!H-S=rhPa^0olF zf*wrWco~NNd~4G&6Mhfw{lyP(@DclAa>D@DJ^LIw+ghdlB=AkSPPgn$j)(o}A5S9O zmcY>;I12H23q0}`+(nV?XBtjuO=a0NVgVbd5+I_nB-9UN~cnAFWYx46Hx2l>$fi-&Fa z>Nnvs>?#~Iq#hblJt=nOp>vEroife&h>fdxVMZ2lKa42 z!;aTCBQrP#e=LAtGJ$wkm$X5s3dlrfWc6xnd*XSc9-%>a+dd00XT|=g5cFCqVr<=d zY<*&t!)LN*fdJdkHJsGek3(XuLaEHaqas{goI29>B;(DJ*NfXz8?j|_9G~mx!TaK^ zG6pG=9LAs2cXxw7Xsk-ic2W%wV<)j{^8<8R0ROmMrT{4P!`_TijaH=;Pc8tC^wBw! zu!l~W=>KRWD%8Pr{_X8;f&*x2NeYlKlb%9bdpipG9P;_1R02r;LnlwrAG7>mARyT{ zrG)8xLqbHv=-neXfn^*TbXEnd7?8MBDeDIij0P|@m64!AfqE6R#A8UdMzLx0HbDi8 zCV|I;NF;<@K8qrWL->1^uRQt>#}m`JoRP9;R^*aEqtUT(k+Sl^03aChNq?zWG7`l` zc36{6lbKl{kCf`ow3eJZb7nIQVAur(G-rCxmSIp4#8#n@WJVmtvuyN{W1owp)nE_rjZK zg(uk|qiF&btg&>i8NGNy3B-g@+x)EG<}7}}C7AlYWc6i{M6DJ`$dN`Rmr<}`sUq2} zi({!26O!??3TgzNRv7}2^4EuFUfhPy{KtRerEOzP?SQ&DuK)C&cOHUYU4I4I+k7aJ z2GkoywW4dAJx};TaylMg7%#oF4oAK7IE;*PWJ_OM9#?$lWBANx{uP;Y4&I;}f!;$< zsRZHk_>DZay;?eI?O&^1uo<}C3FS&LAT>>&^ohB>c>I~CaNLpaKq}e-@8>T=xor;M zDNDeipJBb;g|_qv(!aP6_{HJ|sIkRCZTL#Z17*k|9TerLt2)jS~gA2^2@^;3nWH7B~wc_uCZqq)hE$ zU@CkPmKI#AO4jZ+8dxXnai#+r>aZrO)qp~fhj5eR>CrVflWP}J2bZ+ zg^?Yo5^nX0WwYnd^+zR4$Cn)*Gt_2;rHhlVLUDY0e{cT zoi7F9>5?VmAHSF1PiM#sU5ZWA3@3LqfrAvjC>5oGK!Yx$AubQ~LKILaRRLzCnwheM z%!BZAbWZmBB>t^Z{*r!4ou7=58%95|c%o8g`c#r#Y1!Yw7#W)&I6KFXXcl6@ZGwb9L%g9LPKm=P?Le%8Z)YT#7gs51w810*-(CJ21qI z`rJ!V>|Ly^XqJOPssLR3ZbXOHBXj+CQGT6<(FOs{*{F5?p7tbKK6?SOOO8OM=7ygj zx@s9-(sa9ANJip_JpMPVz2XO`Rh!WTA3ypqTyx1cuw&h`nAo&kripyPpiBmhjuvq5 z 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

K{M)1 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 - -# Example character: Mario - -This example shows how to create a basic character using Llama3.1 as the base model. - -To run this example: - -1. Download the Modelfile -2. `ollama pull llama3.1` to get the base model used in the model file. -3. `ollama create NAME -f ./Modelfile` -4. `ollama run NAME` - -Ask it some questions like "Who are you?" or "Is Peach in trouble again?" - -## Editing this file - -What the model file looks like: - -``` -FROM llama3.1 -PARAMETER temperature 1 -SYSTEM """ -You are Mario from Super Mario Bros, acting as an assistant. -""" -``` - -What if you want to change its behaviour? - -- Try changing the prompt -- Try changing the parameters [Docs](https://github.com/ollama/ollama/blob/main/docs/modelfile.md) -- Try changing the model (e.g. An uncensored model by `FROM wizard-vicuna` this is the wizard-vicuna uncensored model ) - -Once the changes are made, - -1. `ollama create NAME -f ./Modelfile` -2. `ollama run NAME` -3. Iterate until you are happy with the results. - -Notes: - -- This example is for research purposes only. There is no affiliation with any entity. -- When using an uncensored model, please be aware that it may generate offensive content. diff --git a/ollama/examples/python-dockerit/Modelfile b/ollama/examples/python-dockerit/Modelfile deleted file mode 100755 index acd6364..0000000 --- a/ollama/examples/python-dockerit/Modelfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mistral -SYSTEM """ -You are an experienced Devops engineer focused on docker. When given specifications for a particular need or application you know the best way to host that within a docker container. For instance if someone tells you they want an nginx server to host files located at /web you will answer as follows - ----start -FROM nginx:alpine -COPY /myweb /usr/share/nginx/html -EXPOSE 80 ----end - -Notice that the answer you should give is just the contents of the dockerfile with no explanation and there are three dashes and the word start at the beginning and 3 dashes and the word end. The full output can be piped into a file and run as is. Here is another example. The user will ask to launch a Postgres server with a password of abc123. And the response should be - ----start -FROM postgres:latest -ENV POSTGRES_PASSWORD=abc123 -EXPOSE 5432 ----end - -Again it's just the contents of the dockerfile and nothing else. -""" diff --git a/ollama/examples/python-dockerit/README.md b/ollama/examples/python-dockerit/README.md deleted file mode 100755 index 2ba00ce..0000000 --- a/ollama/examples/python-dockerit/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# DockerIt - -DockerIt is a tool to help you build and run your application in a Docker container. It consists of a model that defines the system prompt and model weights to use, along with a python script to then build the container and run the image automatically. - -## Running the Example - -1. Ensure you have the `mattw/dockerit` model installed: - - ```bash - ollama pull mattw/dockerit - ``` - -2. Make sure Docker is running on your machine. - -3. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -4. Run the example: - - ```bash - python dockerit.py "simple postgres server with admin password set to 123" - ``` - -5. Enter the name you would like to use for your container image. - -## Caveats - -This is a simple example. It's assuming the Dockerfile content generated is going to work. In many cases, even with simple web servers, it fails when trying to copy files that don't exist. It's simply an example of what you could possibly do. diff --git a/ollama/examples/python-dockerit/dockerit.py b/ollama/examples/python-dockerit/dockerit.py deleted file mode 100755 index 6a288d9..0000000 --- a/ollama/examples/python-dockerit/dockerit.py +++ /dev/null @@ -1,17 +0,0 @@ -import requests, json, docker, io, sys -inputDescription = " ".join(sys.argv[1:]) -imageName = input("Enter the name of the image: ") -client = docker.from_env() -s = requests.Session() -output="" -with s.post('http://localhost:11434/api/generate', json={'model': 'mattw/dockerit', 'prompt': inputDescription}, stream=True) as r: - for line in r.iter_lines(): - if line: - j = json.loads(line) - if "response" in j: - output = output +j["response"] -output = output[output.find("---start")+9:output.find("---end")-1] -f = io.BytesIO(bytes(output, 'utf-8')) -client.images.build(fileobj=f, tag=imageName) -container = client.containers.run(imageName, detach=True) -print("Container named", container.name, " started with id: ",container.id) diff --git a/ollama/examples/python-dockerit/requirements.txt b/ollama/examples/python-dockerit/requirements.txt deleted file mode 100755 index 6d0eac4..0000000 --- a/ollama/examples/python-dockerit/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -docker \ No newline at end of file diff --git a/ollama/examples/python-json-datagenerator/predefinedschema.py b/ollama/examples/python-json-datagenerator/predefinedschema.py deleted file mode 100755 index 68090ad..0000000 --- a/ollama/examples/python-json-datagenerator/predefinedschema.py +++ /dev/null @@ -1,31 +0,0 @@ -import requests -import json -import random - -model = "llama3.1" -template = { - "firstName": "", - "lastName": "", - "address": { - "street": "", - "city": "", - "state": "", - "zipCode": "" - }, - "phoneNumber": "" -} - -prompt = f"generate one realistically believable sample data set of a persons first name, last name, address in the US, and phone number. \nUse the following template: {json.dumps(template)}." - -data = { - "prompt": prompt, - "model": model, - "format": "json", - "stream": False, - "options": {"temperature": 2.5, "top_p": 0.99, "top_k": 100}, -} - -print(f"Generating a sample user") -response = requests.post("http://localhost:11434/api/generate", json=data, stream=False) -json_data = json.loads(response.text) -print(json.dumps(json.loads(json_data["response"]), indent=2)) diff --git a/ollama/examples/python-json-datagenerator/randomaddresses.py b/ollama/examples/python-json-datagenerator/randomaddresses.py deleted file mode 100755 index 878c980..0000000 --- a/ollama/examples/python-json-datagenerator/randomaddresses.py +++ /dev/null @@ -1,31 +0,0 @@ -import requests -import json -import random - -countries = [ - "United States", - "United Kingdom", - "the Netherlands", - "Germany", - "Mexico", - "Canada", - "France", -] -country = random.choice(countries) -model = "llama3.1" - -prompt = f"generate one realistically believable sample data set of a persons first name, last name, address in {country}, and phone number. Do not use common names. Respond using JSON. Key names should have no backslashes, values should use plain ascii with no special characters." - -data = { - "prompt": prompt, - "model": model, - "format": "json", - "stream": False, - "options": {"temperature": 2.5, "top_p": 0.99, "top_k": 100}, -} - -print(f"Generating a sample user in {country}") -response = requests.post("http://localhost:11434/api/generate", json=data, stream=False) -json_data = json.loads(response.text) - -print(json.dumps(json.loads(json_data["response"]), indent=2)) diff --git a/ollama/examples/python-json-datagenerator/readme.md b/ollama/examples/python-json-datagenerator/readme.md deleted file mode 100755 index 5b444df..0000000 --- a/ollama/examples/python-json-datagenerator/readme.md +++ /dev/null @@ -1,60 +0,0 @@ -# JSON Output Example - -![llmjson 2023-11-10 15_31_31](https://github.com/ollama/ollama/assets/633681/e599d986-9b4a-4118-81a4-4cfe7e22da25) - -There are two python scripts in this example. `randomaddresses.py` generates random addresses from different countries. `predefinedschema.py` sets a template for the model to fill in. - -## Running the Example - -1. Ensure you have the `llama3.1` model installed: - - ```bash - ollama pull llama3.1 - ``` - -2. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -3. Run the Random Addresses example: - - ```bash - python randomaddresses.py - ``` - -4. Run the Predefined Schema example: - - ```bash - python predefinedschema.py - ``` - -## Review the Code - -Both programs are basically the same, with a different prompt for each, demonstrating two different ideas. The key part of getting JSON out of a model is to state in the prompt or system prompt that it should respond using JSON, and specifying the `format` as `json` in the data body. - -```python -prompt = f"generate one realistically believable sample data set of a persons first name, last name, address in {country}, and phone number. Do not use common names. Respond using JSON. Key names should with no backslashes, values should use plain ascii with no special characters." - -data = { - "prompt": prompt, - "model": model, - "format": "json", - "stream": False, - "options": {"temperature": 2.5, "top_p": 0.99, "top_k": 100}, -} -``` - -When running `randomaddresses.py` you will see that the schema changes and adapts to the chosen country. - -In `predefinedschema.py`, a template has been specified in the prompt as well. It's been defined as JSON and then dumped into the prompt string to make it easier to work with. - -Both examples turn streaming off so that we end up with the completed JSON all at once. We need to convert the `response.text` to JSON so that when we output it as a string we can set the indent spacing to make the output easy to read. - -```python -response = requests.post("http://localhost:11434/api/generate", json=data, stream=False) -json_data = json.loads(response.text) - -print(json.dumps(json.loads(json_data["response"]), indent=2)) -``` diff --git a/ollama/examples/python-json-datagenerator/requirements.txt b/ollama/examples/python-json-datagenerator/requirements.txt deleted file mode 100755 index 9688b8e..0000000 --- a/ollama/examples/python-json-datagenerator/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Requests==2.31.0 diff --git a/ollama/examples/python-loganalysis/Modelfile b/ollama/examples/python-loganalysis/Modelfile deleted file mode 100755 index 5237cb6..0000000 --- a/ollama/examples/python-loganalysis/Modelfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM codebooga:latest - -SYSTEM """ -You are a log file analyzer. You will receive a set of lines from a log file for some software application, find the errors and other interesting aspects of the logs, and explain them so a new user can understand what they mean. If there are any steps they can do to resolve them, list the steps in your answer. -""" - -PARAMETER TEMPERATURE 0.3 - diff --git a/ollama/examples/python-loganalysis/loganalysis.py b/ollama/examples/python-loganalysis/loganalysis.py deleted file mode 100755 index 4c7eccb..0000000 --- a/ollama/examples/python-loganalysis/loganalysis.py +++ /dev/null @@ -1,41 +0,0 @@ -import sys -import re -import requests -import json - -# prelines and postlines represent the number of lines of context to include in the output around the error -prelines = 10 -postlines = 10 - -def find_errors_in_log_file(): - if len(sys.argv) < 2: - print("Usage: python loganalysis.py ") - return - - log_file_path = sys.argv[1] - with open(log_file_path, 'r') as log_file: - log_lines = log_file.readlines() - - error_logs = [] - for i, line in enumerate(log_lines): - if "error" in line.lower(): - start_index = max(0, i - prelines) - end_index = min(len(log_lines), i + postlines + 1) - error_logs.extend(log_lines[start_index:end_index]) - - return error_logs - -error_logs = find_errors_in_log_file() - -data = { - "prompt": "\n".join(error_logs), - "model": "mattw/loganalyzer" -} - -response = requests.post("http://localhost:11434/api/generate", json=data, stream=True) -for line in response.iter_lines(): - if line: - json_data = json.loads(line) - if json_data['done'] == False: - print(json_data['response'], end='', flush=True) - diff --git a/ollama/examples/python-loganalysis/logtest.logfile b/ollama/examples/python-loganalysis/logtest.logfile deleted file mode 100755 index e4181bf..0000000 --- a/ollama/examples/python-loganalysis/logtest.logfile +++ /dev/null @@ -1,32 +0,0 @@ -2023-11-10 07:17:40 /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration -2023-11-10 07:17:40 /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ -2023-11-10 07:17:40 /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh -2023-11-10 07:17:40 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf -2023-11-10 07:17:40 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf -2023-11-10 07:17:40 /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh -2023-11-10 07:17:40 /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh -2023-11-10 07:17:40 /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh -2023-11-10 07:17:40 /docker-entrypoint.sh: Configuration complete; ready for start up -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: using the "epoll" event method -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: nginx/1.25.3 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14) -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: OS: Linux 6.4.16-linuxkit -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker processes -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 29 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 30 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 31 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 32 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 33 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 34 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 35 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 36 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 37 -2023-11-10 07:17:40 2023/11/10 13:17:40 [notice] 1#1: start worker process 38 -2023-11-10 07:17:44 192.168.65.1 - - [10/Nov/2023:13:17:43 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" -2023-11-10 07:17:44 2023/11/10 13:17:44 [error] 29#29: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.65.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/" -2023-11-10 07:17:44 192.168.65.1 - - [10/Nov/2023:13:17:44 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost:8080/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" -2023-11-10 07:17:50 2023/11/10 13:17:50 [error] 29#29: *1 open() "/usr/share/nginx/html/ahstat" failed (2: No such file or directory), client: 192.168.65.1, server: localhost, request: "GET /ahstat HTTP/1.1", host: "localhost:8080" -2023-11-10 07:17:50 192.168.65.1 - - [10/Nov/2023:13:17:50 +0000] "GET /ahstat HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" -2023-11-10 07:18:53 2023/11/10 13:18:53 [error] 29#29: *1 open() "/usr/share/nginx/html/ahstat" failed (2: No such file or directory), client: 192.168.65.1, server: localhost, request: "GET /ahstat HTTP/1.1", host: "localhost:8080" -2023-11-10 07:18:53 192.168.65.1 - - [10/Nov/2023:13:18:53 +0000] "GET /ahstat HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" diff --git a/ollama/examples/python-loganalysis/readme.md b/ollama/examples/python-loganalysis/readme.md deleted file mode 100755 index 4be0baa..0000000 --- a/ollama/examples/python-loganalysis/readme.md +++ /dev/null @@ -1,70 +0,0 @@ -# Log Analysis example - -![loganalyzer 2023-11-10 08_53_29](https://github.com/ollama/ollama/assets/633681/ad30f1fc-321f-4953-8914-e30e24db9921) - -This example shows one possible way to create a log file analyzer. It uses the model **mattw/loganalyzer** which is based on **codebooga**, a 34b parameter model. - -To use it, run: - -`python loganalysis.py ` - -You can try this with the `logtest.logfile` file included in this directory. - -## Running the Example - -1. Ensure you have the `mattw/loganalyzer` model installed: - - ```bash - ollama pull mattw/loganalyzer - ``` - -2. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -3. Run the example: - - ```bash - python loganalysis.py logtest.logfile - ``` - -## Review the code - -The first part of this example is a Modelfile that takes `codebooga` and applies a new System Prompt: - -```plaintext -SYSTEM """ -You are a log file analyzer. You will receive a set of lines from a log file for some software application, find the errors and other interesting aspects of the logs, and explain them so a new user can understand what they mean. If there are any steps they can do to resolve them, list the steps in your answer. -""" -``` - -This model is available at https://ollama.com/mattw/loganalyzer. You can customize it and add to your own namespace using the command `ollama create -f ` then `ollama push `. - -Then loganalysis.py scans all the lines in the given log file and searches for the word 'error'. When the word is found, the 10 lines before and after are set as the prompt for a call to the Generate API. - -```python -data = { - "prompt": "\n".join(error_logs), - "model": "mattw/loganalyzer" -} -``` - -Finally, the streamed output is parsed and the response field in the output is printed to the line. - -```python -response = requests.post("http://localhost:11434/api/generate", json=data, stream=True) -for line in response.iter_lines(): - if line: - json_data = json.loads(line) - if json_data['done'] == False: - print(json_data['response'], end='') - -``` - -## Next Steps - -There is a lot more that can be done here. This is a simple way to detect errors, looking for the word error. Perhaps it would be interesting to find anomalous activity in the logs. It could be interesting to create embeddings for each line and compare them, looking for similar lines. Or look into applying Levenshtein Distance algorithms to find similar lines to help identify the anomalous lines. - -Try different models and different prompts to analyze the data. You could consider adding retrieval augmented generation (RAG) to this to help understand newer log formats. diff --git a/ollama/examples/python-loganalysis/requirements.txt b/ollama/examples/python-loganalysis/requirements.txt deleted file mode 100755 index 9688b8e..0000000 --- a/ollama/examples/python-loganalysis/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Requests==2.31.0 diff --git a/ollama/examples/python-rag-newssummary/README.md b/ollama/examples/python-rag-newssummary/README.md deleted file mode 100755 index 51a68be..0000000 --- a/ollama/examples/python-rag-newssummary/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# News Summarizer - -This example goes through a series of steps: - - 1. You choose a topic area (e.g., "news", "NVidia", "music", etc.). - 2. Gets the most recent articles on that topic from various sources. - 3. Uses Ollama to summarize each article. - 4. Creates chunks of sentences from each article. - 5. Uses Sentence Transformers to generate embeddings for each of those chunks. - 6. You enter a question regarding the summaries shown. - 7. Uses Sentence Transformers to generate an embedding for that question. - 8. Uses the embedded question to find the most similar chunks. - 9. Feeds all that to Ollama to generate a good answer to your question based on these news articles. - -This example lets you pick from a few different topic areas, then summarize the most recent x articles for that topic. It then creates chunks of sentences from each article and then generates embeddings for each of those chunks. - -## Running the Example - -1. Ensure you have the `mistral-openorca` model installed: - - ```bash - ollama pull mistral-openorca - ``` - -2. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -3. Run the example: - - ```bash - python summ.py - ``` diff --git a/ollama/examples/python-rag-newssummary/requirements.txt b/ollama/examples/python-rag-newssummary/requirements.txt deleted file mode 100755 index 1a92729..0000000 --- a/ollama/examples/python-rag-newssummary/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -beautifulsoup4==4.12.2 -feedparser==6.0.10 -mattsollamatools==0.0.8 -newspaper3k==0.2.8 -nltk==3.8.1 -numpy==1.24.3 -Requests==2.31.0 -scikit_learn==1.3.0 -sentence_transformers==2.2.2 diff --git a/ollama/examples/python-rag-newssummary/summ.py b/ollama/examples/python-rag-newssummary/summ.py deleted file mode 100755 index 4993cfc..0000000 --- a/ollama/examples/python-rag-newssummary/summ.py +++ /dev/null @@ -1,86 +0,0 @@ -import curses -import json -from utils import get_url_for_topic, topic_urls, menu, getUrls, get_summary, getArticleText, knn_search -import requests -from sentence_transformers import SentenceTransformer -from mattsollamatools import chunker - -if __name__ == "__main__": - chosen_topic = curses.wrapper(menu) - print("Here is your news summary:\n") - urls = getUrls(chosen_topic, n=5) - model = SentenceTransformer('all-MiniLM-L6-v2') - allEmbeddings = [] - - for url in urls: - article={} - article['embeddings'] = [] - article['url'] = url - text = getArticleText(url) - summary = get_summary(text) - chunks = chunker(text) # Use the chunk_text function from web_utils - embeddings = model.encode(chunks) - for (chunk, embedding) in zip(chunks, embeddings): - item = {} - item['source'] = chunk - item['embedding'] = embedding.tolist() # Convert NumPy array to list - item['sourcelength'] = len(chunk) - article['embeddings'].append(item) - - allEmbeddings.append(article) - - print(f"{summary}\n") - - - while True: - context = [] - # Input a question from the user - question = input("Enter your question about the news, or type quit: ") - - if question.lower() == 'quit': - break - - # Embed the user's question - question_embedding = model.encode([question]) - - # Perform KNN search to find the best matches (indices and source text) - best_matches = knn_search(question_embedding, allEmbeddings, k=10) - - - sourcetext="" - for i, (index, source_text) in enumerate(best_matches, start=1): - sourcetext += f"{i}. Index: {index}, Source Text: {source_text}" - - systemPrompt = f"Only use the following information to answer the question. Do not use anything else: {sourcetext}" - - url = "http://localhost:11434/api/generate" - - payload = { - "model": "mistral-openorca", - "prompt": question, - "system": systemPrompt, - "stream": False, - "context": context - } - - # Convert the payload to a JSON string - payload_json = json.dumps(payload) - - # Set the headers to specify JSON content - headers = { - "Content-Type": "application/json" - } - - # Send the POST request - response = requests.post(url, data=payload_json, headers=headers) - - # Check the response - if response.status_code == 200: - output = json.loads(response.text) - context = output['context'] - print(output['response']+ "\n") - - - else: - print(f"Request failed with status code {response.status_code}") - diff --git a/ollama/examples/python-rag-newssummary/utils.py b/ollama/examples/python-rag-newssummary/utils.py deleted file mode 100755 index 0bce011..0000000 --- a/ollama/examples/python-rag-newssummary/utils.py +++ /dev/null @@ -1,108 +0,0 @@ -import curses -import feedparser -import requests -import unicodedata -import json -from newspaper import Article -from bs4 import BeautifulSoup -from nltk.tokenize import sent_tokenize, word_tokenize -import numpy as np -from sklearn.neighbors import NearestNeighbors -from mattsollamatools import chunker - -# Create a dictionary to store topics and their URLs -topic_urls = { - "Mac": "https://9to5mac.com/guides/mac/feed", - "News": "http://www.npr.org/rss/rss.php?id=1001", - "Nvidia": "https://nvidianews.nvidia.com/releases.xml", - "Raspberry Pi": "https://www.raspberrypi.com/news/feed/", - "Music": "https://www.billboard.com/c/music/music-news/feed/" -} - -# Use curses to create a menu of topics -def menu(stdscr): - chosen_topic = get_url_for_topic(stdscr) - url = topic_urls[chosen_topic] if chosen_topic in topic_urls else "Topic not found" - - stdscr.addstr(len(topic_urls) + 3, 0, f"Selected URL for {chosen_topic}: {url}") - stdscr.refresh() - - return chosen_topic - -# You have chosen a topic. Now return the url for that topic -def get_url_for_topic(stdscr): - curses.curs_set(0) # Hide the cursor - stdscr.clear() - - stdscr.addstr(0, 0, "Choose a topic using the arrow keys (Press Enter to select):") - - # Create a list of topics - topics = list(topic_urls.keys()) - current_topic = 0 - - while True: - for i, topic in enumerate(topics): - if i == current_topic: - stdscr.addstr(i + 2, 2, f"> {topic}") - else: - stdscr.addstr(i + 2, 2, f" {topic}") - - stdscr.refresh() - - key = stdscr.getch() - - if key == curses.KEY_DOWN and current_topic < len(topics) - 1: - current_topic += 1 - elif key == curses.KEY_UP and current_topic > 0: - current_topic -= 1 - elif key == 10: # Enter key - return topic_urls[topics[current_topic]] - -# Get the last N URLs from an RSS feed -def getUrls(feed_url, n=20): - feed = feedparser.parse(feed_url) - entries = feed.entries[-n:] - urls = [entry.link for entry in entries] - return urls - -# Often there are a bunch of ads and menus on pages for a news article. This uses newspaper3k to get just the text of just the article. -def getArticleText(url): - article = Article(url) - article.download() - article.parse() - return article.text - -def get_summary(text): - systemPrompt = "Write a concise summary of the text, return your responses with 5 lines that cover the key points of the text given." - prompt = text - - url = "http://localhost:11434/api/generate" - - payload = { - "model": "mistral-openorca", - "prompt": prompt, - "system": systemPrompt, - "stream": False - } - payload_json = json.dumps(payload) - headers = {"Content-Type": "application/json"} - response = requests.post(url, data=payload_json, headers=headers) - - return json.loads(response.text)["response"] - -# Perform K-nearest neighbors (KNN) search -def knn_search(question_embedding, embeddings, k=5): - X = np.array([item['embedding'] for article in embeddings for item in article['embeddings']]) - source_texts = [item['source'] for article in embeddings for item in article['embeddings']] - - # Fit a KNN model on the embeddings - knn = NearestNeighbors(n_neighbors=k, metric='cosine') - knn.fit(X) - - # Find the indices and distances of the k-nearest neighbors - distances, indices = knn.kneighbors(question_embedding, n_neighbors=k) - - # Get the indices and source texts of the best matches - best_matches = [(indices[0][i], source_texts[indices[0][i]]) for i in range(k)] - - return best_matches diff --git a/ollama/examples/python-simplechat/client.py b/ollama/examples/python-simplechat/client.py deleted file mode 100755 index 85043d5..0000000 --- a/ollama/examples/python-simplechat/client.py +++ /dev/null @@ -1,48 +0,0 @@ -import json -import requests - -# NOTE: ollama must be running for this to work, start the ollama app or run `ollama serve` -model = "llama3.1" # TODO: update this for whatever model you wish to use - - -def chat(messages): - r = requests.post( - "http://0.0.0.0:11434/api/chat", - json={"model": model, "messages": messages, "stream": True}, - stream=True - ) - r.raise_for_status() - output = "" - - for line in r.iter_lines(): - body = json.loads(line) - if "error" in body: - raise Exception(body["error"]) - if body.get("done") is False: - message = body.get("message", "") - content = message.get("content", "") - output += content - # the response streams one token at a time, print that as we receive it - print(content, end="", flush=True) - - if body.get("done", False): - message["content"] = output - return message - - -def main(): - messages = [] - - while True: - user_input = input("Enter a prompt: ") - if not user_input: - exit() - print() - messages.append({"role": "user", "content": user_input}) - message = chat(messages) - messages.append(message) - print("\n\n") - - -if __name__ == "__main__": - main() diff --git a/ollama/examples/python-simplechat/readme.md b/ollama/examples/python-simplechat/readme.md deleted file mode 100755 index 4c2ded4..0000000 --- a/ollama/examples/python-simplechat/readme.md +++ /dev/null @@ -1,44 +0,0 @@ -# Simple Chat Example - -The **chat** endpoint is one of two ways to generate text from an LLM with Ollama, and is introduced in version 0.1.14. At a high level, you provide the endpoint an array of objects with a role and content specified. Then with each output and prompt, you add more of those role/content objects, which builds up the history. - -## Running the Example - -1. Ensure you have the `llama3.1` model installed: - - ```bash - ollama pull llama3.1 - ``` - -2. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -3. Run the example: - - ```bash - python client.py - ``` - -## Review the Code - -You can see in the **chat** function that actually calling the endpoint is done simply with: - -```python -r = requests.post( - "http://0.0.0.0:11434/api/chat", - json={"model": model, "messages": messages, "stream": True}, -) -``` - -With the **generate** endpoint, you need to provide a `prompt`. But with **chat**, you provide `messages`. And the resulting stream of responses includes a `message` object with a `content` field. - -The final JSON object doesn't provide the full content, so you will need to build the content yourself. - -In the **main** function, we collect `user_input` and add it as a message to our messages and that is passed to the chat function. When the LLM is done responding the output is added as another message. - -## Next Steps - -In this example, all generations are kept. You might want to experiment with summarizing everything older than 10 conversations to enable longer history with less context being used. diff --git a/ollama/examples/python-simplechat/requirements.txt b/ollama/examples/python-simplechat/requirements.txt deleted file mode 100755 index 9688b8e..0000000 --- a/ollama/examples/python-simplechat/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Requests==2.31.0 diff --git a/ollama/examples/python-simplegenerate/README.md b/ollama/examples/python-simplegenerate/README.md deleted file mode 100755 index a917520..0000000 --- a/ollama/examples/python-simplegenerate/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Simple Generate Example - -This is a simple example using the **Generate** endpoint. - -## Running the Example - -1. Ensure you have the `stablelm-zephyr` model installed: - - ```bash - ollama pull stablelm-zephyr - ``` - -2. Install the Python Requirements. - - ```bash - pip install -r requirements.txt - ``` - -3. Run the example: - - ```bash - python client.py - ``` - -## Review the Code - -The **main** function simply asks for input, then passes that to the generate function. The output from generate is then passed back to generate on the next run. - -The **generate** function uses `requests.post` to call `/api/generate`, passing the model, prompt, and context. The `generate` endpoint returns a stream of JSON blobs that are then iterated through, looking for the response values. That is then printed out. The final JSON object includes the full context of the conversation so far, and that is the return value from the function. diff --git a/ollama/examples/python-simplegenerate/client.py b/ollama/examples/python-simplegenerate/client.py deleted file mode 100755 index 7b5cf81..0000000 --- a/ollama/examples/python-simplegenerate/client.py +++ /dev/null @@ -1,40 +0,0 @@ -import json -import requests - -# NOTE: ollama must be running for this to work, start the ollama app or run `ollama serve` -model = 'stablelm-zephyr' # TODO: update this for whatever model you wish to use - -def generate(prompt, context): - r = requests.post('http://localhost:11434/api/generate', - json={ - 'model': model, - 'prompt': prompt, - 'context': context, - }, - stream=True) - r.raise_for_status() - - for line in r.iter_lines(): - body = json.loads(line) - response_part = body.get('response', '') - # the response streams one token at a time, print that as we receive it - print(response_part, end='', flush=True) - - if 'error' in body: - raise Exception(body['error']) - - if body.get('done', False): - return body['context'] - -def main(): - context = [] # the context stores a conversation history, you can use this to make the model more context aware - while True: - user_input = input("Enter a prompt: ") - if not user_input: - exit() - print() - context = generate(user_input, context) - print() - -if __name__ == "__main__": - main() diff --git a/ollama/examples/python-simplegenerate/requirements.txt b/ollama/examples/python-simplegenerate/requirements.txt deleted file mode 100755 index 9688b8e..0000000 --- a/ollama/examples/python-simplegenerate/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Requests==2.31.0 diff --git a/ollama/examples/typescript-functioncalling/extractemail.ts b/ollama/examples/typescript-functioncalling/extractemail.ts deleted file mode 100755 index a2f0b2d..0000000 --- a/ollama/examples/typescript-functioncalling/extractemail.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { Ollama } from "ollama-node"; -import { readFile } from "fs/promises"; - -// function to be called on events -function reportEvents(name: string, date: string, location: string) { - const nameString = name ? `${name}` : `an event`; - const dateString = date ? ` on ${date}` : ``; - const locationString = location ? ` at ${location}` : ``; - console.log(`You have an event: ${nameString}${dateString}${locationString}`) -} - -// function to be called on addresses -function reportAddresses(address) { - for (const field in address) { - if (address[field]) { - if (field === "city") { - const city = address.city; - const state = address.state ? `, ${address.state}` : ''; - const zip = address.zip ? ` ${address.zip}` : ''; - console.log(`${city}${state}${zip}`); - break; - } else { - console.log(`${address[field]}`); - } - } - } - console.log(``); -} - -async function main() { - - const ollama = new Ollama(); - - const systemprompt = `You will be given a text along with a prompt and a schema. You will have to extract the information requested in the prompt from the text and generate output in JSON observing the schema provided. If the schema shows a type of integer or number, you must only show a integer for that field. A string should always be a valid string. If a value is unknown, leave it empty. Output the JSON with extra spaces to ensure that it pretty prints.` - - const schema = { - "eventsQuantity": { - "type": "integer", - "description": "The number of events in the source text" - }, - "addressesQuantity": { - "type": "integer", - "description": "The number of addresses in the source text" - }, - "events": [{ - name: { - "type": "string", - description: "Name of the event" - }, - "date": { - "type": "string", - "description": "Date of the event" - }, - "location": { - "type": "string", - "description": "Location of the event" - }, - "extraInfo": { - "type": "string", - "description": "Any extra information that is provided about the event." - } - }], - "people": [{ - "name": { - "type": "string", - "description": "Name of the person" - }, - "company": { - "type": "string", - "description": "Name of the company where they work" - }, - "street": { - "type": "string", - "description": "Street address of the person or company. This is only the street name and the numerical address. Do not include city, state, or zip of the address in this field." - }, - "city": { - "type": "string", - "description": "City portion of the address of the person or company" - }, - "state": { - "type": "string", - "description": "State portion of the address of the person or company" - }, - "zip": { - "type": "string", - "description": "Zip code of the person or company" - }, - "extraInfo": { - "type": "string", - "description": "Any extra information that is provided about the location." - } - }] - } - - const textcontent = await readFile("./info.txt", "utf-8").then((text) => text.split(" ").slice(0, 2000).join(" ")); - - const prompt = `The source text is a series of emails that have been put into a single file. They are separated by three dashes. Review the source text and determine the full address of the person sending each of the emails as well as any events that we need to track. If they provide a company address use that. If any extra info is provided, such as a description of the place, or a floor, add it to extraInfo. The first field in the address JSON is quantity of events and should be set to the number of events tracked and the second field should be set to the number of addresses tracked in the file. Don't stuff an event into the output that isn't an event. Only add data to the mostly appropriate field. Don't make up fields that aren't in the schema. If there isn't a value for a field, use null. Output should be in JSON.\n\nSchema: \n${JSON.stringify(schema, null, 2)}\n\nSource Text:\n${textcontent}` - - await ollama.setModel("neural-chat"); - ollama.setSystemPrompt(systemprompt); - ollama.setJSONFormat(true); - const data = await ollama.generate(prompt); - const output = JSON.parse(data.output); - const events = output.events; - const addresses = output.people; - - console.log(`Here are your ${output.eventsQuantity} events:`); - for (const event of events) { - reportEvents(event.name, event.date, event.location); - } - - console.log(`\n\nHere are your ${output.addressesQuantity} addresses:`); - for (const address of addresses) { - reportAddresses(address); - } -} - -main(); \ No newline at end of file diff --git a/ollama/examples/typescript-functioncalling/extractwp.ts b/ollama/examples/typescript-functioncalling/extractwp.ts deleted file mode 100755 index b199607..0000000 --- a/ollama/examples/typescript-functioncalling/extractwp.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Ollama } from "ollama-node"; -import { readFile } from "fs/promises"; - -async function main() { - - const ollama = new Ollama(); - - // Set the system prompt to prepare the model to receive a prompt and a schema and set some rules for the output. - const systemprompt = `You will be given a text along with a prompt and a schema. You will have to extract the information requested in the prompt from the text and generate output in JSON observing the schema provided. If the schema shows a type of integer or number, you must only show a integer for that field. A string should always be a valid string. If a value is unknown, leave it empty. Output the JSON with extra spaces to ensure that it pretty prints.` - - const schema = { - "people": [{ - "name": { - "type": "string", - "description": "Name of the person" - }, - "title": { - "type": "string", - "description": "Title of the person" - } - }], - } - - // Depending on the model chosen, you may be limited by the size of the context window, so limit the context to 2000 words. - const textcontent = await readFile("./wp.txt", "utf-8").then((text) => text.split(" ").slice(0, 2000).join(" ")); - - // Specific instructions for this task - const prompt = `Review the source text and determine the 10 most important people to focus on. Then extract the name and title for those people. Output should be in JSON.\n\nSchema: \n${JSON.stringify(schema, null, 2)}\n\nSource Text:\n${textcontent}` - - await ollama.setModel("neural-chat"); - ollama.setSystemPrompt(systemprompt); - - // setJSONFormat is the equivalent of setting 'format: json' in the API - ollama.setJSONFormat(true); - await ollama.streamingGenerate(prompt, (word) => { process.stdout.write(word) }) -} - -main(); \ No newline at end of file diff --git a/ollama/examples/typescript-functioncalling/info.txt b/ollama/examples/typescript-functioncalling/info.txt deleted file mode 100755 index 4fe0e1c..0000000 --- a/ollama/examples/typescript-functioncalling/info.txt +++ /dev/null @@ -1,17 +0,0 @@ ---- -Hi matt, - -thanks for letting me know that you are going to come today, November 16, for my tea party. My address is 123 Falk St on Bainbridge Island. I live in the house with the red door. I will be home all day so just come by whenever you want. - -Fred - ---- -Great, send the check to our office at 1917 1st St, Seattle, WA 98101. I will let you know when we receive it. - -Mark Richardson -Big Corp ---- -We are looking forward to seeing you at our Local AI Meetup. It will be held on December 3. It will be at the offices of Enormous Co. Our address is 344 1st Ave, Seattle, WA 98101. We will be meeting in the conference room on the 3rd floor. - -Barbara Reilly -Enormous Co. \ No newline at end of file diff --git a/ollama/examples/typescript-functioncalling/package-lock.json b/ollama/examples/typescript-functioncalling/package-lock.json deleted file mode 100755 index c555dda..0000000 --- a/ollama/examples/typescript-functioncalling/package-lock.json +++ /dev/null @@ -1,519 +0,0 @@ -{ - "name": "typescript-functioncalling", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "ollama-node": "^0.1.27" - }, - "devDependencies": { - "tsx": "^4.1.2", - "typescript": "^5.2.2" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/ollama-node": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/ollama-node/-/ollama-node-0.1.27.tgz", - "integrity": "sha512-tFABPf5P0sXCR5USA31E3tqbge5h/4uf/t5j8/rPvHDo0SDwXeN0kah2J7hIqqkYlO1vLRs0uLC1/Mprgv9t2g==", - "dependencies": { - "@types/node": "^20.8.4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/tsx": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.1.2.tgz", - "integrity": "sha512-1spM1bFV6MP2s4tO4tDC7g52fsaFdtEWdO4GfGdqi20qUgPbnAJqixOyIAvCSx1DDj3YIUB4CD06owTWUsOAuQ==", - "dev": true, - "dependencies": { - "esbuild": "~0.18.20", - "get-tsconfig": "^4.7.2", - "source-map-support": "^0.5.21" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - } - } -} diff --git a/ollama/examples/typescript-functioncalling/package.json b/ollama/examples/typescript-functioncalling/package.json deleted file mode 100755 index 4e8fff8..0000000 --- a/ollama/examples/typescript-functioncalling/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "dependencies": { - "ollama-node": "^0.1.27" - }, - "devDependencies": { - "tsx": "^4.1.2", - "typescript": "^5.2.2" - } -} diff --git a/ollama/examples/typescript-functioncalling/readme.md b/ollama/examples/typescript-functioncalling/readme.md deleted file mode 100755 index d29379a..0000000 --- a/ollama/examples/typescript-functioncalling/readme.md +++ /dev/null @@ -1,28 +0,0 @@ -# Function calling - -![function calling 2023-11-16 16_12_58](https://github.com/ollama/ollama/assets/633681/a0acc247-9746-45ab-b325-b65dfbbee4fb) - -One of the features added to some models is 'function calling'. It's a bit of a confusing name. It's understandable if you think that means the model can call functions, but that's not what it means. Function calling simply means that the output of the model is formatted in JSON, using a preconfigured schema, and uses the expected types. Then your code can use the output of the model and call functions with it. Using the JSON format in Ollama, you can use any model for function calling. - -The two examples provided can extract information out of the provided texts. The first example uses the first couple of chapters from War and Peace by Lev Nikolayevich Tolstoy, and extracts the names and titles of the characters introduced in the story. The second example uses a more complicated schema to pull out addresses and event information from a series of emails. - -## Running the examples - -1. Clone this repo and navigate to the `examples/typescript-functioncalling` directory. -2. Install the dependencies with `npm install`. -3. Review the `wp.txt` file. -4. Run `tsx extractwp.ts`. -5. Review the `info.txt` file. -6. Run `tsx extractemail.ts`. - -## Review the Code - -Both examples do roughly the same thing with different source material. They both use the same system prompt, which tells the model to expect some instructions and a schema. Then we inject the schema into the prompt and generate an answer. - -The first example, `extractwp.ts`, outputs the resulting JSON to the console, listing the characters introduced at the start of War and Peace. The second example, `extractemail.ts`, is a bit more complicated, extracting two different types of information: addresses and events. It outputs the results to a JSON blob, then the addresses are handed off to one function called `reportAddresses` and the events are handed off to another function called `reportEvents`. - -Notice that both examples are using the model from Intel called `neural-chat`. This is not a model tuned for function calling, yet it performs very well at this task. - -## Next Steps - -Try exporting some of your real emails to the input file and seeing how well the model does. Try pointing the first example at other books. You could even have it cycle through all the sections and maybe add up the number of times any character is seen throughout the book, determining the most important characters. You can also try out different models. diff --git a/ollama/examples/typescript-functioncalling/wp.txt b/ollama/examples/typescript-functioncalling/wp.txt deleted file mode 100755 index 0ef8486..0000000 --- a/ollama/examples/typescript-functioncalling/wp.txt +++ /dev/null @@ -1,183 +0,0 @@ -"Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you don't tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist - I really believe he is Antichrist - I will have nothing more to do with you and you are no longer my friend, no longer my 'faithful slave,' as you call yourself! But how do you do? I see I have frightened you - sit down and tell me all the news." - -It was in July, 1805, and the speaker was the well-known Anna Pavlovna Scherer, maid of honor and favorite of the Empress Marya Fedorovna. With these words she greeted Prince Vasili Kuragin, a man of high rank and importance, who was the first to arrive at her reception. Anna Pavlovna had had a cough for some days. She was, as she said, suffering from la grippe; grippe being then a new word in St. Petersburg, used only by the elite. - -All her invitations without exception, written in French, and delivered by a scarlet-liveried footman that morning, ran as follows: - -"If you have nothing better to do, Count (or Prince), and if the prospect of spending an evening with a poor invalid is not too terrible, I shall be very charmed to see you tonight between 7 and 10 - Annette Scherer." - -"Heavens! what a virulent attack!" replied the prince, not in the least disconcerted by this reception. He had just entered, wearing an embroidered court uniform, knee breeches, and shoes, and had stars on his breast and a serene expression on his flat face. He spoke in that refined French in which our grandfathers not only spoke but thought, and with the gentle, patronizing intonation natural to a man of importance who had grown old in society and at court. He went up to Anna Pavlovna, kissed her hand, presenting to her his bald, scented, and shining head, and complacently seated himself on the sofa. - -"First of all, dear friend, tell me how you are. Set your friend's mind at rest," said he without altering his tone, beneath the politeness and affected sympathy of which indifference and even irony could be discerned. - -"Can one be well while suffering morally? Can one be calm in times like these if one has any feeling?" said Anna Pavlovna. "You are staying the whole evening, I hope?" - -"And the fete at the English ambassador's? Today is Wednesday. I must put in an appearance there," said the prince. "My daughter is coming for me to take me there." - -"I thought today's fete had been canceled. I confess all these festivities and fireworks are becoming wearisome." - -"If they had known that you wished it, the entertainment would have been put off," said the prince, who, like a wound-up clock, by force of habit said things he did not even wish to be believed. - -"Don't tease! Well, and what has been decided about Novosiltsev's dispatch? You know everything." - -"What can one say about it?" replied the prince in a cold, listless tone. "What has been decided? They have decided that Buonaparte has burnt his boats, and I believe that we are ready to burn ours." - -Prince Vasili always spoke languidly, like an actor repeating a stale part. Anna Pavlovna Scherer on the contrary, despite her forty years, overflowed with animation and impulsiveness. To be an enthusiast had become her social vocation and, sometimes even when she did not feel like it, she became enthusiastic in order not to disappoint the expectations of those who knew her. The subdued smile which, though it did not suit her faded features, always played round her lips expressed, as in a spoiled child, a continual consciousness of her charming defect, which she neither wished, nor could, nor considered it necessary, to correct. - -In the midst of a conversation on political matters Anna Pavlovna burst out: - -"Oh, don't speak to me of Austria. Perhaps I don't understand things, but Austria never has wished, and does not wish, for war. She is betraying us! Russia alone must save Europe. Our gracious sovereign recognizes his high vocation and will be true to it. That is the one thing I have faith in! Our good and wonderful sovereign has to perform the noblest role on earth, and he is so virtuous and noble that God will not forsake him. He will fulfill his vocation and crush the hydra of revolution, which has become more terrible than ever in the person of this murderer and villain! We alone must avenge the blood of the just one.... Whom, I ask you, can we rely on?... England with her commercial spirit will not and cannot understand the Emperor Alexander's loftiness of soul. She has refused to evacuate Malta. She wanted to find, and still seeks, some secret motive in our actions. What answer did Novosiltsev get? None. The English have not understood and cannot understand the self-abnegation of our Emperor who wants nothing for himself, but only desires the good of mankind. And what have they promised? Nothing! And what little they have promised they will not perform! Prussia has always declared that Buonaparte is invincible, and that all Europe is powerless before him.... And I don't believe a word that Hardenburg says, or Haugwitz either. This famous Prussian neutrality is just a trap. I have faith only in God and the lofty destiny of our adored monarch. He will save Europe!" - -She suddenly paused, smiling at her own impetuosity. - -"I think," said the prince with a smile, "that if you had been sent instead of our dear Wintzingerode you would have captured the King of Prussia's consent by assault. You are so eloquent. Will you give me a cup of tea?" - -"In a moment. A propos," she added, becoming calm again, "I am expecting two very interesting men tonight, le Vicomte de Mortemart, who is connected with the Montmorencys through the Rohans, one of the best French families. He is one of the genuine emigres, the good ones. And also the Abbe Morio. Do you know that profound thinker? He has been received by the Emperor. Had you heard?" - -"I shall be delighted to meet them," said the prince. "But tell me," he added with studied carelessness as if it had only just occurred to him, though the question he was about to ask was the chief motive of his visit, "is it true that the Dowager Empress wants Baron Funke to be appointed first secretary at Vienna? The baron by all accounts is a poor creature." - -Prince Vasili wished to obtain this post for his son, but others were trying through the Dowager Empress Marya Fedorovna to secure it for the baron. - -Anna Pavlovna almost closed her eyes to indicate that neither she nor anyone else had a right to criticize what the Empress desired or was pleased with. - -"Baron Funke has been recommended to the Dowager Empress by her sister," was all she said, in a dry and mournful tone. - -As she named the Empress, Anna Pavlovna's face suddenly assumed an expression of profound and sincere devotion and respect mingled with sadness, and this occurred every time she mentioned her illustrious patroness. She added that Her Majesty had deigned to show Baron Funke beaucoup d'estime, and again her face clouded over with sadness. - -The prince was silent and looked indifferent. But, with the womanly and courtierlike quickness and tact habitual to her, Anna Pavlovna wished both to rebuke him (for daring to speak as he had done of a man recommended to the Empress) and at the same time to console him, so she said: - -"Now about your family. Do you know that since your daughter came out everyone has been enraptured by her? They say she is amazingly beautiful." - -The prince bowed to signify his respect and gratitude. - -"I often think," she continued after a short pause, drawing nearer to the prince and smiling amiably at him as if to show that political and social topics were ended and the time had come for intimate conversation - "I often think how unfairly sometimes the joys of life are distributed. Why has fate given you two such splendid children? I don't speak of Anatole, your youngest. I don't like him," she added in a tone admitting of no rejoinder and raising her eyebrows. "Two such charming children. And really you appreciate them less than anyone, and so you don't deserve to have them." - -And she smiled her ecstatic smile. - -"I can't help it," said the prince. "Lavater would have said I lack the bump of paternity." - -"Don't joke; I mean to have a serious talk with you. Do you know I am dissatisfied with your younger son? Between ourselves" (and her face assumed its melancholy expression), "he was mentioned at Her Majesty's and you were pitied...." - -The prince answered nothing, but she looked at him significantly, awaiting a reply. He frowned. - -"What would you have me do?" he said at last. "You know I did all a father could for their education, and they have both turned out fools. Hippolyte is at least a quiet fool, but Anatole is an active one. That is the only difference between them." He said this smiling in a way more natural and animated than usual, so that the wrinkles round his mouth very clearly revealed something unexpectedly coarse and unpleasant. - -"And why are children born to such men as you? If you were not a father there would be nothing I could reproach you with," said Anna Pavlovna, looking up pensively. - -"I am your faithful slave and to you alone I can confess that my children are the bane of my life. It is the cross I have to bear. That is how I explain it to myself. It can't be helped!" - -He said no more, but expressed his resignation to cruel fate by a gesture. Anna Pavlovna meditated. - -"Have you never thought of marrying your prodigal son Anatole?" she asked. "They say old maids have a mania for matchmaking, and though I don't feel that weakness in myself as yet, I know a little person who is very unhappy with her father. She is a relation of yours, Princess Mary Bolkonskaya." - -Prince Vasili did not reply, though, with the quickness of memory and perception befitting a man of the world, he indicated by a movement of the head that he was considering this information. - -"Do you know," he said at last, evidently unable to check the sad current of his thoughts, "that Anatole is costing me forty thousand rubles a year? And," he went on after a pause, "what will it be in five years, if he goes on like this?" Presently he added: "That's what we fathers have to put up with.... Is this princess of yours rich?" - -"Her father is very rich and stingy. He lives in the country. He is the well-known Prince Bolkonski who had to retire from the army under the late Emperor, and was nicknamed 'the King of Prussia.' He is very clever but eccentric, and a bore. The poor girl is very unhappy. She has a brother; I think you know him, he married Lise Meinen lately. He is an aide-de-camp of Kutuzov's and will be here tonight." - -"Listen, dear Annette," said the prince, suddenly taking Anna Pavlovna's hand and for some reason drawing it downwards. "Arrange that affair for me and I shall always be your most devoted slave-slafe with an f, as a village elder of mine writes in his reports. She is rich and of good family and that's all I want." - -And with the familiarity and easy grace peculiar to him, he raised the maid of honor's hand to his lips, kissed it, and swung it to and fro as he lay back in his armchair, looking in another direction. - -"Attendez," said Anna Pavlovna, reflecting, "I'll speak to Lise, young Bolkonski's wife, this very evening, and perhaps the thing can be arranged. It shall be on your family's behalf that I'll start my apprenticeship as old maid." - -Anna Pavlovna's drawing room was gradually filling. The highest Petersburg society was assembled there: people differing widely in age and character but alike in the social circle to which they belonged. Prince Vasili's daughter, the beautiful Helene, came to take her father to the ambassador's entertainment; she wore a ball dress and her badge as maid of honor. The youthful little Princess Bolkonskaya, known as la femme la plus seduisante de Petersbourg, * was also there. She had been married during the previous winter, and being pregnant did not go to any large gatherings, but only to small receptions. Prince Vasili's son, Hippolyte, had come with Mortemart, whom he introduced. The Abbe Morio and many others had also come. - -* The most fascinating woman in Petersburg. - -To each new arrival Anna Pavlovna said, "You have not yet seen my aunt," or "You do not know my aunt?" and very gravely conducted him or her to a little old lady, wearing large bows of ribbon in her cap, who had come sailing in from another room as soon as the guests began to arrive; and slowly turning her eyes from the visitor to her aunt, Anna Pavlovna mentioned each one's name and then left them. - -Each visitor performed the ceremony of greeting this old aunt whom not one of them knew, not one of them wanted to know, and not one of them cared about; Anna Pavlovna observed these greetings with mournful and solemn interest and silent approval. The aunt spoke to each of them in the same words, about their health and her own, and the health of Her Majesty, "who, thank God, was better today." And each visitor, though politeness prevented his showing impatience, left the old woman with a sense of relief at having performed a vexatious duty and did not return to her the whole evening. - -The young Princess Bolkonskaya had brought some work in a gold-embroidered velvet bag. Her pretty little upper lip, on which a delicate dark down was just perceptible, was too short for her teeth, but it lifted all the more sweetly, and was especially charming when she occasionally drew it down to meet the lower lip. As is always the case with a thoroughly attractive woman, her defect - the shortness of her upper lip and her half-open mouth - seemed to be her own special and peculiar form of beauty. Everyone brightened at the sight of this pretty young woman, so soon to become a mother, so full of life and health, and carrying her burden so lightly. Old men and dull dispirited young ones who looked at her, after being in her company and talking to her a little while, felt as if they too were becoming, like her, full of life and health. All who talked to her, and at each word saw her bright smile and the constant gleam of her white teeth, thought that they were in a specially amiable mood that day. - -The little princess went round the table with quick, short, swaying steps, her workbag on her arm, and gaily spreading out her dress sat down on a sofa near the silver samovar, as if all she was doing was a pleasure to herself and to all around her. "I have brought my work," said she in French, displaying her bag and addressing all present. "Mind, Annette, I hope you have not played a wicked trick on me," she added, turning to her hostess. "You wrote that it was to be quite a small reception, and just see how badly I am dressed." And she spread out her arms to show her short-waisted, lace-trimmed, dainty gray dress, girdled with a broad ribbon just below the breast. - -"Soyez tranquille, Lise, you will always be prettier than anyone else," replied Anna Pavlovna. - -"You know," said the princess in the same tone of voice and still in French, turning to a general, "my husband is deserting me? He is going to get himself killed. Tell me what this wretched war is for?" she added, addressing Prince Vasili, and without waiting for an answer she turned to speak to his daughter, the beautiful Helene. - -"What a delightful woman this little princess is!" said Prince Vasili to Anna Pavlovna. - -One of the next arrivals was a stout, heavily built young man with close-cropped hair, spectacles, the light-colored breeches fashionable at that time, a very high ruffle, and a brown dress coat. This stout young man was an illegitimate son of Count Bezukhov, a well-known grandee of Catherine's time who now lay dying in Moscow. The young man had not yet entered either the military or civil service, as he had only just returned from abroad where he had been educated, and this was his first appearance in society. Anna Pavlovna greeted him with the nod she accorded to the lowest hierarchy in her drawing room. But in spite of this lowest-grade greeting, a look of anxiety and fear, as at the sight of something too large and unsuited to the place, came over her face when she saw Pierre enter. Though he was certainly rather bigger than the other men in the room, her anxiety could only have reference to the clever though shy, but observant and natural, expression which distinguished him from everyone else in that drawing room. - -"It is very good of you, Monsieur Pierre, to come and visit a poor invalid," said Anna Pavlovna, exchanging an alarmed glance with her aunt as she conducted him to her. - -Pierre murmured something unintelligible, and continued to look round as if in search of something. On his way to the aunt he bowed to the little princess with a pleased smile, as to an intimate acquaintance. - -Anna Pavlovna's alarm was justified, for Pierre turned away from the aunt without waiting to hear her speech about Her Majesty's health. Anna Pavlovna in dismay detained him with the words: "Do you know the Abbe Morio? He is a most interesting man." - -"Yes, I have heard of his scheme for perpetual peace, and it is very interesting but hardly feasible." - -"You think so?" rejoined Anna Pavlovna in order to say something and get away to attend to her duties as hostess. But Pierre now committed a reverse act of impoliteness. First he had left a lady before she had finished speaking to him, and now he continued to speak to another who wished to get away. With his head bent, and his big feet spread apart, he began explaining his reasons for thinking the abbe's plan chimerical. - -"We will talk of it later," said Anna Pavlovna with a smile. - -And having got rid of this young man who did not know how to behave, she resumed her duties as hostess and continued to listen and watch, ready to help at any point where the conversation might happen to flag. As the foreman of a spinning mill, when he has set the hands to work, goes round and notices here a spindle that has stopped or there one that creaks or makes more noise than it should, and hastens to check the machine or set it in proper motion, so Anna Pavlovna moved about her drawing room, approaching now a silent, now a too-noisy group, and by a word or slight rearrangement kept the conversational machine in steady, proper, and regular motion. But amid these cares her anxiety about Pierre was evident. She kept an anxious watch on him when he approached the group round Mortemart to listen to what was being said there, and again when he passed to another group whose center was the abbe. - -Pierre had been educated abroad, and this reception at Anna Pavlovna's was the first he had attended in Russia. He knew that all the intellectual lights of Petersburg were gathered there and, like a child in a toyshop, did not know which way to look, afraid of missing any clever conversation that was to be heard. Seeing the self-confident and refined expression on the faces of those present he was always expecting to hear something very profound. At last he came up to Morio. Here the conversation seemed interesting and he stood waiting for an opportunity to express his own views, as young people are fond of doing. - -CHAPTER III -Anna Pavlovna's reception was in full swing. The spindles hummed steadily and ceaselessly on all sides. With the exception of the aunt, beside whom sat only one elderly lady, who with her thin careworn face was rather out of place in this brilliant society, the whole company had settled into three groups. One, chiefly masculine, had formed round the abbe. Another, of young people, was grouped round the beautiful Princess Helene, Prince Vasili's daughter, and the little Princess Bolkonskaya, very pretty and rosy, though rather too plump for her age. The third group was gathered round Mortemart and Anna Pavlovna. - -The vicomte was a nice-looking young man with soft features and polished manners, who evidently considered himself a celebrity but out of politeness modestly placed himself at the disposal of the circle in which he found himself. Anna Pavlovna was obviously serving him up as a treat to her guests. As a clever maitre d'hotel serves up as a specially choice delicacy a piece of meat that no one who had seen it in the kitchen would have cared to eat, so Anna Pavlovna served up to her guests, first the vicomte and then the abbe, as peculiarly choice morsels. The group about Mortemart immediately began discussing the murder of the Duc d'Enghien. The vicomte said that the Duc d'Enghien had perished by his own magnanimity, and that there were particular reasons for Buonaparte's hatred of him. - -"Ah, yes! Do tell us all about it, Vicomte," said Anna Pavlovna, with a pleasant feeling that there was something A la Louis XV in the sound of that sentence: "Contez nous cela, Vicomte." - -The vicomte bowed and smiled courteously in token of his willingness to comply. Anna Pavlovna arranged a group round him, inviting everyone to listen to his tale. - -"The vicomte knew the duc personally," whispered Anna Pavlovna to one of the guests. "The vicomte is a wonderful raconteur," said she to another. "How evidently he belongs to the best society," said she to a third; and the vicomte was served up to the company in the choicest and most advantageous style, like a well-garnished joint of roast beef on a hot dish. - -The vicomte wished to begin his story and gave a subtle smile. - -"Come over here, Helene, dear," said Anna Pavlovna to the beautiful young princess who was sitting some way off, the center of another group. - -The princess smiled. She rose with the same unchanging smile with which she had first entered the room - the smile of a perfectly beautiful woman. With a slight rustle of her white dress trimmed with moss and ivy, with a gleam of white shoulders, glossy hair, and sparkling diamonds, she passed between the men who made way for her, not looking at any of them but smiling on all, as if graciously allowing each the privilege of admiring her beautiful figure and shapely shoulders, back, and bosom - which in the fashion of those days were very much exposed - and she seemed to bring the glamour of a ballroom with her as she moved toward Anna Pavlovna. Helene was so lovely that not only did she not show any trace of coquetry, but on the contrary she even appeared shy of her unquestionable and all too victorious beauty. She seemed to wish, but to be unable, to diminish its effect. - -"How lovely!" said everyone who saw her; and the vicomte lifted his shoulders and dropped his eyes as if startled by something extraordinary when she took her seat opposite and beamed upon him also with her unchanging smile. - -"Madame, I doubt my ability before such an audience," said he, smilingly inclining his head. - -The princess rested her bare round arm on a little table and considered a reply unnecessary. She smilingly waited. All the time the story was being told she sat upright, glancing now at her beautiful round arm, altered in shape by its pressure on the table, now at her still more beautiful bosom, on which she readjusted a diamond necklace. From time to time she smoothed the folds of her dress, and whenever the story produced an effect she glanced at Anna Pavlovna, at once adopted just the expression she saw on the maid of honor's face, and again relapsed into her radiant smile. - -The little princess had also left the tea table and followed Helene. - -"Wait a moment, I'll get my work.... Now then, what are you thinking of?" she went on, turning to Prince Hippolyte. "Fetch me my workbag." - -There was a general movement as the princess, smiling and talking merrily to everyone at once, sat down and gaily arranged herself in her seat. - -"Now I am all right," she said, and asking the vicomte to begin, she took up her work. - -Prince Hippolyte, having brought the workbag, joined the circle and moving a chair close to hers seated himself beside her. - -Le charmant Hippolyte was surprising by his extraordinary resemblance to his beautiful sister, but yet more by the fact that in spite of this resemblance he was exceedingly ugly. His features were like his sister's, but while in her case everything was lit up by a joyous, self-satisfied, youthful, and constant smile of animation, and by the wonderful classic beauty of her figure, his face on the contrary was dulled by imbecility and a constant expression of sullen self-confidence, while his body was thin and weak. His eyes, nose, and mouth all seemed puckered into a vacant, wearied grimace, and his arms and legs always fell into unnatural positions. - -"It's not going to be a ghost story?" said he, sitting down beside the princess and hastily adjusting his lorgnette, as if without this instrument he could not begin to speak. - -"Why no, my dear fellow," said the astonished narrator, shrugging his shoulders. - -"Because I hate ghost stories," said Prince Hippolyte in a tone which showed that he only understood the meaning of his words after he had uttered them. - -He spoke with such self-confidence that his hearers could not be sure whether what he said was very witty or very stupid. He was dressed in a dark-green dress coat, knee breeches of the color of cuisse de nymphe effrayee, as he called it, shoes, and silk stockings. - -The vicomte told his tale very neatly. It was an anecdote, then current, to the effect that the Duc d'Enghien had gone secretly to Paris to visit Mademoiselle George; that at her house he came upon Bonaparte, who also enjoyed the famous actress' favors, and that in his presence Napoleon happened to fall into one of the fainting fits to which he was subject, and was thus at the duc's mercy. The latter spared him, and this magnanimity Bonaparte subsequently repaid by death. - -The story was very pretty and interesting, especially at the point where the rivals suddenly recognized one another; and the ladies looked agitated. - -"Charming!" said Anna Pavlovna with an inquiring glance at the little princess. - -"Charming!" whispered the little princess, sticking the needle into her work as if to testify that the interest and fascination of the story prevented her from going on with it. - -The vicomte appreciated this silent praise and smiling gratefully prepared to continue, but just then Anna Pavlovna, who had kept a watchful eye on the young man who so alarmed her, noticed that he was talking too loudly and vehemently with the abbe, so she hurried to the rescue. Pierre had managed to start a conversation with the abbe about the balance of power, and the latter, evidently interested by the young man's simple-minded eagerness, was explaining his pet theory. Both were talking and listening too eagerly and too naturally, which was why Anna Pavlovna disapproved. - -"The means are ... the balance of power in Europe and the rights of the people," the abbe was saying. "It is only necessary for one powerful nation like Russia - barbaric as she is said to be - to place herself disinterestedly at the head of an alliance having for its object the maintenance of the balance of power of Europe, and it would save the world!" - -"But how are you to get that balance?" Pierre was beginning. - -At that moment Anna Pavlovna came up and, looking severely at Pierre, asked the Italian how he stood Russian climate. The Italian's face instantly changed and assumed an offensively affected, sugary expression, evidently habitual to him when conversing with women. - -"I am so enchanted by the brilliancy of the wit and culture of the society, more especially of the feminine society, in which I have had the honor of being received, that I have not yet had time to think of the climate," said he. - -Not letting the abbe and Pierre escape, Anna Pavlovna, the more conveniently to keep them under observation, brought them into the larger circle. - diff --git a/ollama/examples/typescript-mentors/.gitignore b/ollama/examples/typescript-mentors/.gitignore deleted file mode 100755 index d5f19d8..0000000 --- a/ollama/examples/typescript-mentors/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -package-lock.json diff --git a/ollama/examples/typescript-mentors/README.md b/ollama/examples/typescript-mentors/README.md deleted file mode 100755 index d3611a5..0000000 --- a/ollama/examples/typescript-mentors/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Ask the Mentors - -This example demonstrates how one would create a set of 'mentors' you can have a conversation with. The mentors are generated using the `character-generator.ts` file. This will use **Stable Beluga 70b** to create a bio and list of verbal ticks and common phrases used by each person. Then `mentors.ts` will take a question, and choose three of the 'mentors' and start a conversation with them. Occasionally, they will talk to each other, and other times they will just deliver a set of monologues. It's fun to see what they do and say. - -## Usage - -1. Add llama3 to have the mentors ask your questions: - - ```bash - ollama pull llama3 - ``` - -2. Install prerequisites: - - ```bash - npm install - ``` - -3. Ask a question: - - ```bash - npm start "what is a jackalope" - ``` - -You can also add your own character to be chosen at random when you ask a question. - -1. Make sure you have the right model installed: - - ```bash - ollama pull stablebeluga2:70b-q4_K_M - ``` - -2. Create a new character: - - ```bash - npm run charactergen "Lorne Greene" - ``` - - You can choose any well-known person you like. This example will create `lornegreene/Modelfile`. - -3. Now you can create a model with this command: - - ```bash - ollama create /lornegreene -f lornegreene/Modelfile - ``` - - `username` is whatever name you set up when you signed up at [https://ollama.com/signup](https://ollama.com/signup). - -4. To add this to your mentors, you will have to update the code as follows. On line 8 of `mentors.ts`, add an object to the array, replacing `` with the username you used above. - - ```bash - {ns: "", char: "Lorne Greene"} - ``` - -## Review the Code - -There are two scripts you can run in this example. The first is the main script to ask the mentors a question. The other one lets you generate a character to add to the mentors. Both scripts are mostly about adjusting the prompts at each inference stage. - -### mentors.ts - -In the **main** function, it starts by generating a list of mentors. This chooses 3 from a list of interesting characters. Then we ask for a question, and then things get interesting. We set the prompt for each of the 3 mentors a little differently. And the 2nd and 3rd mentors see what the previous folks said. The other functions in mentors sets the prompts for each mentor. - -### character-generator.ts - -**Character Generator** simply customizes the prompt to build a character profile for any famous person. And most of the script is just tweaking the prompt. This uses Stable Beluga 2 70b parameters. The 70b models tend to do better writing a bio about a character than smaller models, and Stable Beluga seemed to do better than Llama 2. Since this is used at development time for the characters, it doesn't affect the runtime of asking the mentors for their input. diff --git a/ollama/examples/typescript-mentors/character-generator.ts b/ollama/examples/typescript-mentors/character-generator.ts deleted file mode 100755 index dc5d2f5..0000000 --- a/ollama/examples/typescript-mentors/character-generator.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Ollama } from 'ollama-node' -import fs from 'fs'; -import path from 'path'; - -async function characterGenerator() { - const character = process.argv[2]; - console.log(`You are creating a character for ${character}.`); - const foldername = character.replace(/\s/g, '').toLowerCase(); - const directory = path.join(__dirname, foldername); - if (!fs.existsSync(directory)) { - fs.mkdirSync(directory, { recursive: true }); - } - - const ollama = new Ollama(); - ollama.setModel("stablebeluga2:70b-q4_K_M"); - const bio = await ollama.generate(`create a bio of ${character} in a single long paragraph. Instead of saying '${character} is...' or '${character} was...' use language like 'You are...' or 'You were...'. Then create a paragraph describing the speaking mannerisms and style of ${character}. Don't include anything about how ${character} looked or what they sounded like, just focus on the words they said. Instead of saying '${character} would say...' use language like 'You should say...'. If you use quotes, always use single quotes instead of double quotes. If there are any specific words or phrases you used a lot, show how you used them. `); - - const thecontents = `FROM llama3\nSYSTEM """\n${bio.response.replace(/(\r\n|\n|\r)/gm, " ").replace('would', 'should')} All answers to questions should be related back to what you are most known for.\n"""`; - - fs.writeFile(path.join(directory, 'Modelfile'), thecontents, (err: any) => { - if (err) throw err; - console.log('The file has been saved!'); - }); -} - -characterGenerator(); diff --git a/ollama/examples/typescript-mentors/mentors.ts b/ollama/examples/typescript-mentors/mentors.ts deleted file mode 100755 index 17d7047..0000000 --- a/ollama/examples/typescript-mentors/mentors.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Ollama } from 'ollama-node'; - -const mentorCount = 3; -const ollama = new Ollama(); -type Mentor = { ns: string, char: string }; - -function getMentors(): Mentor[] { - const mentors = [{ ns: 'mattw', char: 'Gary Vaynerchuk' }, { ns: 'mattw', char: 'Kanye West'}, {ns: 'mattw', char: 'Martha Stewart'}, {ns: 'mattw', char: 'Neil deGrasse Tyson'}, {ns: 'mattw', char: 'Owen Wilson'}, {ns: 'mattw', char: 'Ronald Reagan'}, {ns: 'mattw', char: 'Donald Trump'}, {ns: 'mattw', char: 'Barack Obama'}, {ns: 'mattw', char: 'Jeff Bezos'}]; - const chosenMentors: Mentor[] = []; - for (let i = 0; i < mentorCount; i++) { - const mentor = mentors[Math.floor(Math.random() * mentors.length)]; - chosenMentors.push(mentor); - mentors.splice(mentors.indexOf(mentor), 1); - } - return chosenMentors; -} - -function getMentorFileName(mentor: Mentor): string { - const model = mentor.char.toLowerCase().replace(/\s/g, ''); - return `${mentor.ns}/${model}`; -} - -async function getSystemPrompt(mentor: Mentor, isLast: boolean, question: string): Promise { - ollama.setModel(getMentorFileName(mentor)); - const info = await ollama.showModelInfo() - let SystemPrompt = info.system || ''; - SystemPrompt += ` You should continue the conversation as if you were ${mentor} and acknowledge the people before you in the conversation. You should adopt their mannerisms and tone, but also not use language they wouldn't use. If they are not known to know about the concept in the question, don't offer an answer. Your answer should be no longer than 1 paragraph. And definitely try not to sound like anyone else. Don't repeat any slang or phrases already used. And if it is a question the original ${mentor} wouldn't have know the answer to, just say that you don't know, in the style of ${mentor}. And think about the time the person lived. Don't use terminology that they wouldn't have used.` - - if (isLast) { - SystemPrompt += ` End your answer with something like I hope our answers help you out`; - } else { - SystemPrompt += ` Remember, this is a conversation, so you don't need a conclusion, but end your answer with a question related to the first question: "${question}".`; - } - return SystemPrompt; -} - -async function main() { - const mentors = getMentors(); - const question = process.argv[2]; - let theConversation = `Here is the conversation so far.\nYou: ${question}\n` - - for await (const mentor of mentors) { - const SystemPrompt = await getSystemPrompt(mentor, mentor === mentors[mentorCount - 1], question); - ollama.setModel(getMentorFileName(mentor)); - ollama.setSystemPrompt(SystemPrompt); - let output = ''; - process.stdout.write(`\n${mentor.char}: `); - for await (const chunk of ollama.streamingGenerate(theConversation + `Continue the conversation as if you were ${mentor.char} on the question "${question}".`)) { - if (chunk.response) { - output += chunk.response; - process.stdout.write(chunk.response); - } else { - process.stdout.write('\n'); - } - } - theConversation += `${mentor.char}: ${output}\n\n` - } -} - -main(); \ No newline at end of file diff --git a/ollama/examples/typescript-mentors/package.json b/ollama/examples/typescript-mentors/package.json deleted file mode 100755 index 537f3df..0000000 --- a/ollama/examples/typescript-mentors/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "scripts": { - "charactergen": "tsx character-generator.ts", - "start": "tsx mentors.ts" - }, - "dependencies": { - "fs": "^0.0.1-security", - "ollama-node": "^0.0.3", - "path": "^0.12.7" - }, - "devDependencies": { - "tsx": "^4.6.2", - "typescript": "^5.3.3" - } -} diff --git a/ollama/examples/typescript-simplechat/client.ts b/ollama/examples/typescript-simplechat/client.ts deleted file mode 100755 index 8ad113b..0000000 --- a/ollama/examples/typescript-simplechat/client.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as readline from "readline"; - -const model = "llama3.1"; -type Message = { - role: "assistant" | "user" | "system"; - content: string; -} -const messages: Message[] = [{ - role: "system", - content: "You are a helpful AI agent." -}] - -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout -}) - -async function chat(messages: Message[]): Promise { - const body = { - model: model, - messages: messages - } - - const response = await fetch("http://localhost:11434/api/chat", { - method: "POST", - body: JSON.stringify(body) - }) - - const reader = response.body?.getReader() - if (!reader) { - throw new Error("Failed to read response body") - } - let content = "" - while (true) { - const { done, value } = await reader.read() - if (done) { - break; - } - const rawjson = new TextDecoder().decode(value); - const json = JSON.parse(rawjson) - - if (json.done === false) { - process.stdout.write(json.message.content); - content += json.message.content - } - - } - return { role: "assistant", content: content }; -} - -async function askQuestion(): Promise { - return new Promise((resolve) => { - rl.question("\n\nAsk a question: (press enter alone to quit)\n\n", async (user_input) => { - if (user_input.trim() === "") { - rl.close(); - console.log("Thankyou. Goodbye.\n") - console.log("=======\nHere is the message history that was used in this conversation.\n=======\n") - messages.forEach(message => { - console.log(message) - }) - resolve(); - } else { - console.log(); - messages.push({ role: "user", content: user_input }); - messages.push(await chat(messages)); - await askQuestion(); // Ask the next question - } - }); - }); -} - -async function main() { - await askQuestion(); - -} - -main(); diff --git a/ollama/examples/typescript-simplechat/package.json b/ollama/examples/typescript-simplechat/package.json deleted file mode 100755 index 6ae8c1a..0000000 --- a/ollama/examples/typescript-simplechat/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "scripts": { - "start": "tsx client.ts" - }, - "dependencies": { - "@types/node": "^20.10.4", - "prompt-sync": "^4.2.0", - "readline": "^1.3.0", - "tsx": "^4.6.2", - "typescript": "^5.3.3" - } - } \ No newline at end of file diff --git a/ollama/examples/typescript-simplechat/readme.md b/ollama/examples/typescript-simplechat/readme.md deleted file mode 100755 index 5635b9d..0000000 --- a/ollama/examples/typescript-simplechat/readme.md +++ /dev/null @@ -1,35 +0,0 @@ -# Simple Chat Example - -The **chat** endpoint, available as of v0.1.14, is one of two ways to generate text from an LLM with Ollama. At a high level, you provide the endpoint an array of message objects with a role and content specified. Then with each output and prompt, you add more messages, which builds up the history. - -## Run the Example - -`npm start` - -## Review the Code - -You can see in the **chat** function that is actually calling the endpoint is simply done with: - -```typescript -const body = { - model: model, - messages: messages -} - -const response = await fetch("http://localhost:11434/api/chat", { - method: "POST", - body: JSON.stringify(body) -}) -``` - -With the **generate** endpoint, you need to provide a `prompt`. But with **chat**, you provide `messages`. And the resulting stream of responses includes a `message` object with a `content` field. - -The final JSON object doesn't provide the full content, so you will need to build the content yourself. In this example, **chat** takes the full array of messages and outputs the resulting message from this call of the chat endpoint. - -In the **askQuestion** function, we collect `user_input` and add it as a message to our messages, and that is passed to the chat function. When the LLM is done responding, the output is added as another message to the messages array. - -At the end, you will see a printout of all the messages. - -## Next Steps - -In this example, all generations are kept. You might want to experiment with summarizing everything older than 10 conversations to enable longer history with less context being used. diff --git a/ollama/format/bytes.go b/ollama/format/bytes.go deleted file mode 100755 index 13d8575..0000000 --- a/ollama/format/bytes.go +++ /dev/null @@ -1,65 +0,0 @@ -package format - -import ( - "fmt" - "math" -) - -const ( - Byte = 1 - - KiloByte = Byte * 1000 - MegaByte = KiloByte * 1000 - GigaByte = MegaByte * 1000 - TeraByte = GigaByte * 1000 - - KibiByte = Byte * 1024 - MebiByte = KibiByte * 1024 - GibiByte = MebiByte * 1024 -) - -func HumanBytes(b int64) string { - var value float64 - var unit string - - switch { - case b >= TeraByte: - value = float64(b) / TeraByte - unit = "TB" - case b >= GigaByte: - value = float64(b) / GigaByte - unit = "GB" - case b >= MegaByte: - value = float64(b) / MegaByte - unit = "MB" - case b >= KiloByte: - value = float64(b) / KiloByte - unit = "KB" - default: - return fmt.Sprintf("%d B", b) - } - - switch { - case value >= 100: - return fmt.Sprintf("%d %s", int(value), unit) - case value >= 10: - return fmt.Sprintf("%d %s", int(value), unit) - case value != math.Trunc(value): - return fmt.Sprintf("%.1f %s", value, unit) - default: - return fmt.Sprintf("%d %s", int(value), unit) - } -} - -func HumanBytes2(b uint64) string { - switch { - case b >= GibiByte: - return fmt.Sprintf("%.1f GiB", float64(b)/GibiByte) - case b >= MebiByte: - return fmt.Sprintf("%.1f MiB", float64(b)/MebiByte) - case b >= KibiByte: - return fmt.Sprintf("%.1f KiB", float64(b)/KibiByte) - default: - return fmt.Sprintf("%d B", b) - } -} diff --git a/ollama/format/format.go b/ollama/format/format.go deleted file mode 100755 index ac50570..0000000 --- a/ollama/format/format.go +++ /dev/null @@ -1,34 +0,0 @@ -package format - -import ( - "fmt" - "math" - "strconv" -) - -const ( - Thousand = 1000 - Million = Thousand * 1000 - Billion = Million * 1000 -) - -func HumanNumber(b uint64) string { - switch { - case b >= Billion: - number := float64(b) / Billion - if number == math.Floor(number) { - return fmt.Sprintf("%.0fB", number) // no decimals if whole number - } - return fmt.Sprintf("%.1fB", number) // one decimal if not a whole number - case b >= Million: - number := float64(b) / Million - if number == math.Floor(number) { - return fmt.Sprintf("%.0fM", number) // no decimals if whole number - } - return fmt.Sprintf("%.2fM", number) // two decimals if not a whole number - case b >= Thousand: - return fmt.Sprintf("%.0fK", float64(b)/Thousand) - default: - return strconv.FormatUint(b, 10) - } -} diff --git a/ollama/format/format_test.go b/ollama/format/format_test.go deleted file mode 100755 index bff3278..0000000 --- a/ollama/format/format_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package format - -import ( - "testing" -) - -func TestHumanNumber(t *testing.T) { - type testCase struct { - input uint64 - expected string - } - - testCases := []testCase{ - {0, "0"}, - {1000000, "1M"}, - {125000000, "125M"}, - {500500000, "500.50M"}, - {500550000, "500.55M"}, - {1000000000, "1B"}, - {2800000000, "2.8B"}, - {2850000000, "2.9B"}, - {1000000000000, "1000B"}, - } - - for _, tc := range testCases { - t.Run(tc.expected, func(t *testing.T) { - result := HumanNumber(tc.input) - if result != tc.expected { - t.Errorf("Expected %s, got %s", tc.expected, result) - } - }) - } -} diff --git a/ollama/format/time.go b/ollama/format/time.go deleted file mode 100755 index 7406284..0000000 --- a/ollama/format/time.go +++ /dev/null @@ -1,70 +0,0 @@ -package format - -import ( - "fmt" - "math" - "strings" - "time" -) - -// humanDuration returns a human-readable approximation of a -// duration (eg. "About a minute", "4 hours ago", etc.). -func humanDuration(d time.Duration) string { - seconds := int(d.Seconds()) - - switch { - case seconds < 1: - return "Less than a second" - case seconds == 1: - return "1 second" - case seconds < 60: - return fmt.Sprintf("%d seconds", seconds) - } - - minutes := int(d.Minutes()) - switch { - case minutes == 1: - return "About a minute" - case minutes < 60: - return fmt.Sprintf("%d minutes", minutes) - } - - hours := int(math.Round(d.Hours())) - switch { - case hours == 1: - return "About an hour" - case hours < 48: - return fmt.Sprintf("%d hours", hours) - case hours < 24*7*2: - return fmt.Sprintf("%d days", hours/24) - case hours < 24*30*2: - return fmt.Sprintf("%d weeks", hours/24/7) - case hours < 24*365*2: - return fmt.Sprintf("%d months", hours/24/30) - } - - return fmt.Sprintf("%d years", int(d.Hours())/24/365) -} - -func HumanTime(t time.Time, zeroValue string) string { - return humanTime(t, zeroValue) -} - -func HumanTimeLower(t time.Time, zeroValue string) string { - return strings.ToLower(humanTime(t, zeroValue)) -} - -func humanTime(t time.Time, zeroValue string) string { - if t.IsZero() { - return zeroValue - } - - delta := time.Since(t) - if int(delta.Hours())/24/365 < -20 { - return "Forever" - } else if delta < 0 { - return humanDuration(-delta) + " from now" - } - - return humanDuration(delta) + " ago" -} diff --git a/ollama/format/time_test.go b/ollama/format/time_test.go deleted file mode 100755 index bd0ba9a..0000000 --- a/ollama/format/time_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package format - -import ( - "testing" - "time" -) - -func assertEqual(t *testing.T, a interface{}, b interface{}) { - if a != b { - t.Errorf("Assert failed, expected %v, got %v", b, a) - } -} - -func TestHumanTime(t *testing.T) { - now := time.Now() - - t.Run("zero value", func(t *testing.T) { - assertEqual(t, HumanTime(time.Time{}, "never"), "never") - }) - - t.Run("time in the future", func(t *testing.T) { - v := now.Add(48 * time.Hour) - assertEqual(t, HumanTime(v, ""), "2 days from now") - }) - - t.Run("time in the past", func(t *testing.T) { - v := now.Add(-48 * time.Hour) - assertEqual(t, HumanTime(v, ""), "2 days ago") - }) - - t.Run("soon", func(t *testing.T) { - v := now.Add(800 * time.Millisecond) - assertEqual(t, HumanTime(v, ""), "Less than a second from now") - }) - - t.Run("time way in the future", func(t *testing.T) { - v := now.Add(24 * time.Hour * 365 * 200) - assertEqual(t, HumanTime(v, ""), "Forever") - }) - - t.Run("time way in the future lowercase", func(t *testing.T) { - v := now.Add(24 * time.Hour * 365 * 200) - assertEqual(t, HumanTimeLower(v, ""), "forever") - }) -} diff --git a/ollama/go.mod b/ollama/go.mod deleted file mode 100755 index 2e0c661..0000000 --- a/ollama/go.mod +++ /dev/null @@ -1,78 +0,0 @@ -module github.com/ollama/ollama - -go 1.22.0 - -require ( - github.com/containerd/console v1.0.3 - github.com/emirpasic/gods v1.18.1 - github.com/gin-gonic/gin v1.10.0 - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/uuid v1.1.2 - github.com/olekukonko/tablewriter v0.0.5 - github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.9.0 - github.com/x448/float16 v0.8.4 - golang.org/x/sync v0.3.0 -) - -require ( - github.com/agnivade/levenshtein v1.1.1 - github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1 - github.com/google/go-cmp v0.6.0 - github.com/mattn/go-runewidth v0.0.14 - github.com/nlpodyssey/gopickle v0.3.0 - github.com/pdevine/tensor v0.0.0-20240510204454-f88f4562727c -) - -require ( - github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect - github.com/chewxy/hm v1.0.0 // indirect - github.com/chewxy/math32 v1.10.1 // indirect - github.com/cloudwego/base64x v0.1.4 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect - github.com/kr/text v0.2.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.2.0 // indirect - github.com/xtgo/set v1.0.0 // indirect - go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gonum.org/v1/gonum v0.15.0 // indirect - gorgonia.org/vecf32 v0.9.0 // indirect - gorgonia.org/vecf64 v0.9.0 // indirect -) - -require ( - github.com/bytedance/sonic v1.11.6 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gin-contrib/cors v1.7.2 - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.20.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 - golang.org/x/term v0.20.0 - golang.org/x/text v0.15.0 - google.golang.org/protobuf v1.34.1 - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/ollama/go.sum b/ollama/go.sum deleted file mode 100755 index 926ed26..0000000 --- a/ollama/go.sum +++ /dev/null @@ -1,364 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 h1:q4dksr6ICHXqG5hm0ZW5IHyeEJXoIJSOZeBLmWPNeIQ= -github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= -github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= -github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chewxy/hm v1.0.0 h1:zy/TSv3LV2nD3dwUEQL2VhXeoXbb9QkpmdRAVUFiA6k= -github.com/chewxy/hm v1.0.0/go.mod h1:qg9YI4q6Fkj/whwHR1D+bOGeF7SniIP40VweVepLjg0= -github.com/chewxy/math32 v1.0.0/go.mod h1:Miac6hA1ohdDUTagnvJy/q+aNnEk16qWUdb8ZVhvCN0= -github.com/chewxy/math32 v1.10.1 h1:LFpeY0SLJXeaiej/eIp2L40VYfscTvKh/FSEZ68uMkU= -github.com/chewxy/math32 v1.10.1/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= -github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1 h1:cBzrdJPAFBsgCrDPnZxlp1dF2+k4r1kVpD7+1S1PVjY= -github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1/go.mod h1:uw2gLcxEuYUlAd/EXyjc/v55nd3+47YAgWbSXVxPrNI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= -github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ= -github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nlpodyssey/gopickle v0.3.0 h1:BLUE5gxFLyyNOPzlXxt6GoHEMMxD0qhsE4p0CIQyoLw= -github.com/nlpodyssey/gopickle v0.3.0/go.mod h1:f070HJ/yR+eLi5WmM1OXJEGaTpuJEUiib19olXgYha0= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pdevine/tensor v0.0.0-20240510204454-f88f4562727c h1:GwiUUjKefgvSNmv3NCvI/BL0kDebW6Xa+kcdpdc1mTY= -github.com/pdevine/tensor v0.0.0-20240510204454-f88f4562727c/go.mod h1:PSojXDXF7TbgQiD6kkd98IHOS0QqTyUEaWRiS8+BLu8= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= -github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xtgo/set v1.0.0 h1:6BCNBRv3ORNDQ7fyoJXRv+tstJz3m1JVFQErfeZz2pY= -github.com/xtgo/set v1.0.0/go.mod h1:d3NHzGzSa0NmB2NhFyECA+QdRp29oEn2xbT+TpeFoM8= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 h1:lGdhQUN/cnWdSH3291CUuxSEqc+AsGTiDxPP3r2J0l4= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= -golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= -gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorgonia.org/vecf32 v0.9.0 h1:PClazic1r+JVJ1dEzRXgeiVl4g1/Hf/w+wUSqnco1Xg= -gorgonia.org/vecf32 v0.9.0/go.mod h1:NCc+5D2oxddRL11hd+pCB1PEyXWOyiQxfZ/1wwhOXCA= -gorgonia.org/vecf64 v0.9.0 h1:bgZDP5x0OzBF64PjMGC3EvTdOoMEcmfAh1VCUnZFm1A= -gorgonia.org/vecf64 v0.9.0/go.mod h1:hp7IOWCnRiVQKON73kkC/AUMtEXyf9kGlVrtPQ9ccVA= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/ollama/gpu/amd_common.go b/ollama/gpu/amd_common.go deleted file mode 100755 index 2839cb7..0000000 --- a/ollama/gpu/amd_common.go +++ /dev/null @@ -1,99 +0,0 @@ -//go:build linux || windows - -package gpu - -import ( - "errors" - "log/slog" - "os" - "path/filepath" - "runtime" - "strings" -) - -// Determine if the given ROCm lib directory is usable by checking for existence of some glob patterns -func rocmLibUsable(libDir string) bool { - slog.Debug("evaluating potential rocm lib dir " + libDir) - for _, g := range ROCmLibGlobs { - res, _ := filepath.Glob(filepath.Join(libDir, g)) - if len(res) == 0 { - return false - } - } - return true -} - -func GetSupportedGFX(libDir string) ([]string, error) { - var ret []string - files, err := filepath.Glob(filepath.Join(libDir, "rocblas", "library", "TensileLibrary_lazy_gfx*.dat")) - if err != nil { - return nil, err - } - for _, file := range files { - ret = append(ret, strings.TrimSuffix(strings.TrimPrefix(filepath.Base(file), "TensileLibrary_lazy_"), ".dat")) - } - return ret, nil -} - -func rocmGetVisibleDevicesEnv(gpuInfo []GpuInfo) (string, string) { - ids := []string{} - for _, info := range gpuInfo { - if info.Library != "rocm" { - // TODO shouldn't happen if things are wired correctly... - slog.Debug("rocmGetVisibleDevicesEnv skipping over non-rocm device", "library", info.Library) - continue - } - ids = append(ids, info.ID) - } - return "HIP_VISIBLE_DEVICES", strings.Join(ids, ",") -} - -func commonAMDValidateLibDir() (string, error) { - // Favor our bundled version - - // Installer payload location if we're running the installed binary - exe, err := os.Executable() - if err == nil { - rocmTargetDir := filepath.Join(filepath.Dir(exe), "rocm") - if rocmLibUsable(rocmTargetDir) { - slog.Debug("detected ROCM next to ollama executable " + rocmTargetDir) - return rocmTargetDir, nil - } - } - - // Prefer explicit HIP env var - hipPath := os.Getenv("HIP_PATH") - if hipPath != "" { - hipLibDir := filepath.Join(hipPath, "bin") - if rocmLibUsable(hipLibDir) { - slog.Debug("detected ROCM via HIP_PATH=" + hipPath) - return hipLibDir, nil - } - } - - // Scan the LD_LIBRARY_PATH or PATH - pathEnv := "LD_LIBRARY_PATH" - if runtime.GOOS == "windows" { - pathEnv = "PATH" - } - - paths := os.Getenv(pathEnv) - for _, path := range filepath.SplitList(paths) { - d, err := filepath.Abs(path) - if err != nil { - continue - } - if rocmLibUsable(d) { - return d, nil - } - } - - // Well known location(s) - for _, path := range RocmStandardLocations { - if rocmLibUsable(path) { - return path, nil - } - } - - return "", errors.New("no suitable rocm found, falling back to CPU") -} diff --git a/ollama/gpu/amd_hip_windows.go b/ollama/gpu/amd_hip_windows.go deleted file mode 100755 index 2cea282..0000000 --- a/ollama/gpu/amd_hip_windows.go +++ /dev/null @@ -1,147 +0,0 @@ -package gpu - -import ( - "errors" - "fmt" - "log/slog" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -const ( - hipSuccess = 0 - hipErrorNoDevice = 100 -) - -type hipDevicePropMinimal struct { - Name [256]byte - unused1 [140]byte - GcnArchName [256]byte // gfx#### - iGPU int // Doesn't seem to actually report correctly - unused2 [128]byte -} - -// Wrap the amdhip64.dll library for GPU discovery -type HipLib struct { - dll windows.Handle - hipGetDeviceCount uintptr - hipGetDeviceProperties uintptr - hipMemGetInfo uintptr - hipSetDevice uintptr - hipDriverGetVersion uintptr -} - -func NewHipLib() (*HipLib, error) { - // At runtime we depend on v6, so discover GPUs with the same library for a consistent set of GPUs - h, err := windows.LoadLibrary("amdhip64_6.dll") - if err != nil { - return nil, fmt.Errorf("unable to load amdhip64_6.dll, please make sure to upgrade to the latest amd driver: %w", err) - } - hl := &HipLib{} - hl.dll = h - hl.hipGetDeviceCount, err = windows.GetProcAddress(hl.dll, "hipGetDeviceCount") - if err != nil { - return nil, err - } - hl.hipGetDeviceProperties, err = windows.GetProcAddress(hl.dll, "hipGetDeviceProperties") - if err != nil { - return nil, err - } - hl.hipMemGetInfo, err = windows.GetProcAddress(hl.dll, "hipMemGetInfo") - if err != nil { - return nil, err - } - hl.hipSetDevice, err = windows.GetProcAddress(hl.dll, "hipSetDevice") - if err != nil { - return nil, err - } - hl.hipDriverGetVersion, err = windows.GetProcAddress(hl.dll, "hipDriverGetVersion") - if err != nil { - return nil, err - } - return hl, nil -} - -// The hip library only evaluates the HIP_VISIBLE_DEVICES variable at startup -// so we have to unload/reset the library after we do our initial discovery -// to make sure our updates to that variable are processed by llama.cpp -func (hl *HipLib) Release() { - err := windows.FreeLibrary(hl.dll) - if err != nil { - slog.Warn("failed to unload amdhip64.dll", "error", err) - } - hl.dll = 0 -} - -func (hl *HipLib) AMDDriverVersion() (driverMajor, driverMinor int, err error) { - if hl.dll == 0 { - return 0, 0, errors.New("dll has been unloaded") - } - var version int - status, _, err := syscall.SyscallN(hl.hipDriverGetVersion, uintptr(unsafe.Pointer(&version))) - if status != hipSuccess { - return 0, 0, fmt.Errorf("failed call to hipDriverGetVersion: %d %s", status, err) - } - - slog.Debug("hipDriverGetVersion", "version", version) - driverMajor = version / 10000000 - driverMinor = (version - (driverMajor * 10000000)) / 100000 - - return driverMajor, driverMinor, nil -} - -func (hl *HipLib) HipGetDeviceCount() int { - if hl.dll == 0 { - slog.Error("dll has been unloaded") - return 0 - } - var count int - status, _, err := syscall.SyscallN(hl.hipGetDeviceCount, uintptr(unsafe.Pointer(&count))) - if status == hipErrorNoDevice { - slog.Info("AMD ROCm reports no devices found") - return 0 - } - if status != hipSuccess { - slog.Warn("failed call to hipGetDeviceCount", "status", status, "error", err) - } - return count -} - -func (hl *HipLib) HipSetDevice(device int) error { - if hl.dll == 0 { - return errors.New("dll has been unloaded") - } - status, _, err := syscall.SyscallN(hl.hipSetDevice, uintptr(device)) - if status != hipSuccess { - return fmt.Errorf("failed call to hipSetDevice: %d %s", status, err) - } - return nil -} - -func (hl *HipLib) HipGetDeviceProperties(device int) (*hipDevicePropMinimal, error) { - if hl.dll == 0 { - return nil, errors.New("dll has been unloaded") - } - var props hipDevicePropMinimal - status, _, err := syscall.SyscallN(hl.hipGetDeviceProperties, uintptr(unsafe.Pointer(&props)), uintptr(device)) - if status != hipSuccess { - return nil, fmt.Errorf("failed call to hipGetDeviceProperties: %d %s", status, err) - } - return &props, nil -} - -// free, total, err -func (hl *HipLib) HipMemGetInfo() (uint64, uint64, error) { - if hl.dll == 0 { - return 0, 0, errors.New("dll has been unloaded") - } - var totalMemory uint64 - var freeMemory uint64 - status, _, err := syscall.SyscallN(hl.hipMemGetInfo, uintptr(unsafe.Pointer(&freeMemory)), uintptr(unsafe.Pointer(&totalMemory))) - if status != hipSuccess { - return 0, 0, fmt.Errorf("failed call to hipMemGetInfo: %d %s", status, err) - } - return freeMemory, totalMemory, nil -} diff --git a/ollama/gpu/amd_linux.go b/ollama/gpu/amd_linux.go deleted file mode 100755 index fee5834..0000000 --- a/ollama/gpu/amd_linux.go +++ /dev/null @@ -1,460 +0,0 @@ -package gpu - -import ( - "bufio" - "errors" - "fmt" - "io" - "log/slog" - "os" - "path/filepath" - "regexp" - "slices" - "sort" - "strconv" - "strings" - - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/format" -) - -// Discovery logic for AMD/ROCm GPUs - -const ( - // DriverVersionFile = "/sys/module/amdgpu/version" - DriverVersionFile = "/sys/module/hydcu/version" - AMDNodesSysfsDir = "/sys/class/kfd/kfd/topology/nodes/" - GPUPropertiesFileGlob = AMDNodesSysfsDir + "*/properties" - - // Prefix with the node dir - GPUTotalMemoryFileGlob = "mem_banks/*/properties" // size_in_bytes line - - // Direct Rendering Manager sysfs location - DRMDeviceDirGlob = "/sys/class/drm/card*/device" - DRMTotalMemoryFile = "mem_info_vram_total" - DRMUsedMemoryFile = "mem_info_vram_used" - - // In hex; properties file is in decimal - DRMUniqueIDFile = "unique_id" - DRMVendorFile = "vendor" - DRMDeviceFile = "device" -) - -var ( - // Used to validate if the given ROCm lib is usable - // ROCmLibGlobs = []string{"libhipblas.so.2*", "rocblas"} // TODO - probably include more coverage of files here... - ROCmLibGlobs = []string{"libhipblas.so.0.1","rocblas"} - // RocmStandardLocations = []string{"/opt/rocm/lib", "/usr/lib64"} - RocmStandardLocations = []string{"/opt/dtk/lib", "/usr/lib64"} -) - -// Gather GPU information from the amdgpu driver if any supported GPUs are detected -func AMDGetGPUInfo() []RocmGPUInfo { - resp := []RocmGPUInfo{} - if !AMDDetected() { - return resp - } - - // Opportunistic logging of driver version to aid in troubleshooting - driverMajor, driverMinor, err := AMDDriverVersion() - if err != nil { - // TODO - if we see users crash and burn with the upstreamed kernel this can be adjusted to hard-fail rocm support and fallback to CPU - slog.Warn("ollama recommends running the https://www.amd.com/en/support/linux-drivers", "error", err) - } - - // Determine if the user has already pre-selected which GPUs to look at, then ignore the others - var visibleDevices []string - hipVD := envconfig.HipVisibleDevices() // zero based index only - rocrVD := envconfig.RocrVisibleDevices() // zero based index or UUID, but consumer cards seem to not support UUID - gpuDO := envconfig.GpuDeviceOrdinal() // zero based index - switch { - // TODO is this priorty order right? - case hipVD != "": - visibleDevices = strings.Split(hipVD, ",") - case rocrVD != "": - visibleDevices = strings.Split(rocrVD, ",") - // TODO - since we don't yet support UUIDs, consider detecting and reporting here - // all our test systems show GPU-XX indicating UUID is not supported - case gpuDO != "": - visibleDevices = strings.Split(gpuDO, ",") - } - - gfxOverride := envconfig.HsaOverrideGfxVersion() - var supported []string - libDir := "" - - // The amdgpu driver always exposes the host CPU(s) first, but we have to skip them and subtract - // from the other IDs to get alignment with the HIP libraries expectations (zero is the first GPU, not the CPU) - matches, _ := filepath.Glob(GPUPropertiesFileGlob) - sort.Slice(matches, func(i, j int) bool { - // /sys/class/kfd/kfd/topology/nodes//properties - a, err := strconv.ParseInt(filepath.Base(filepath.Dir(matches[i])), 10, 64) - if err != nil { - slog.Debug("parse err", "error", err, "match", matches[i]) - return false - } - b, err := strconv.ParseInt(filepath.Base(filepath.Dir(matches[j])), 10, 64) - if err != nil { - slog.Debug("parse err", "error", err, "match", matches[i]) - return false - } - return a < b - }) - cpuCount := 0 - for _, match := range matches { - slog.Debug("evaluating amdgpu node " + match) - fp, err := os.Open(match) - if err != nil { - slog.Debug("failed to open sysfs node", "file", match, "error", err) - continue - } - defer fp.Close() - nodeID, err := strconv.Atoi(filepath.Base(filepath.Dir(match))) - if err != nil { - slog.Debug("failed to parse node ID", "error", err) - continue - } - - scanner := bufio.NewScanner(fp) - isCPU := false - var major, minor, patch uint64 - var vendor, device, uniqueID uint64 - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - // Note: we could also use "cpu_cores_count X" where X is greater than zero to detect CPUs - if strings.HasPrefix(line, "gfx_target_version") { - ver := strings.Fields(line) - - // Detect CPUs - if len(ver) == 2 && ver[1] == "0" { - slog.Debug("detected CPU " + match) - isCPU = true - break - } - - if len(ver) != 2 || len(ver[1]) < 5 { - slog.Warn("malformed "+match, "gfx_target_version", line) - // If this winds up being a CPU, our offsets may be wrong - continue - } - l := len(ver[1]) - var err1, err2, err3 error - patch, err1 = strconv.ParseUint(ver[1][l-2:l], 10, 32) - minor, err2 = strconv.ParseUint(ver[1][l-4:l-2], 10, 32) - major, err3 = strconv.ParseUint(ver[1][:l-4], 10, 32) - if err1 != nil || err2 != nil || err3 != nil { - slog.Debug("malformed int " + line) - continue - } - } else if strings.HasPrefix(line, "vendor_id") { - ver := strings.Fields(line) - if len(ver) != 2 { - slog.Debug("malformed", "vendor_id", line) - continue - } - vendor, err = strconv.ParseUint(ver[1], 10, 64) - if err != nil { - slog.Debug("malformed", "vendor_id", line, "error", err) - } - } else if strings.HasPrefix(line, "device_id") { - ver := strings.Fields(line) - if len(ver) != 2 { - slog.Debug("malformed", "device_id", line) - continue - } - device, err = strconv.ParseUint(ver[1], 10, 64) - if err != nil { - slog.Debug("malformed", "device_id", line, "error", err) - } - } else if strings.HasPrefix(line, "unique_id") { - ver := strings.Fields(line) - if len(ver) != 2 { - slog.Debug("malformed", "unique_id", line) - continue - } - uniqueID, err = strconv.ParseUint(ver[1], 10, 64) - if err != nil { - slog.Debug("malformed", "unique_id", line, "error", err) - } - } - // TODO - any other properties we want to extract and record? - // vendor_id + device_id -> pci lookup for "Name" - // Other metrics that may help us understand relative performance between multiple GPUs - } - - // Note: while ./mem_banks/*/used_memory exists, it doesn't appear to take other VRAM consumers - // into consideration, so we instead map the device over to the DRM driver sysfs nodes which - // do reliably report VRAM usage. - - if isCPU { - cpuCount++ - continue - } - - // CPUs are always first in the list - gpuID := nodeID - cpuCount - - // Shouldn't happen, but just in case... - if gpuID < 0 { - slog.Error("unexpected amdgpu sysfs data resulted in negative GPU ID, please set OLLAMA_DEBUG=1 and report an issue") - return nil - } - - if int(major) < RocmComputeMin { - slog.Warn(fmt.Sprintf("amdgpu too old gfx%d%x%x", major, minor, patch), "gpu", gpuID) - continue - } - - // Look up the memory for the current node - totalMemory := uint64(0) - usedMemory := uint64(0) - var usedFile string - mapping := []struct { - id uint64 - filename string - }{ - {vendor, DRMVendorFile}, - {device, DRMDeviceFile}, - {uniqueID, DRMUniqueIDFile}, // Not all devices will report this - } - slog.Debug("mapping amdgpu to drm sysfs nodes", "amdgpu", match, "vendor", vendor, "device", device, "unique_id", uniqueID) - // Map over to DRM location to find the total/free memory - drmMatches, _ := filepath.Glob(DRMDeviceDirGlob) - for _, devDir := range drmMatches { - matched := true - for _, m := range mapping { - if m.id == 0 { - // Null ID means it didn't populate, so we can't use it to match - continue - } - filename := filepath.Join(devDir, m.filename) - buf, err := os.ReadFile(filename) - if err != nil { - slog.Debug("failed to read sysfs node", "file", filename, "error", err) - matched = false - break - } - // values here are in hex, strip off the lead 0x and parse so we can compare the numeric (decimal) values in amdgpu - cmp, err := strconv.ParseUint(strings.TrimPrefix(strings.TrimSpace(string(buf)), "0x"), 16, 64) - if err != nil { - slog.Debug("failed to parse sysfs node", "file", filename, "error", err) - matched = false - break - } - if cmp != m.id { - matched = false - break - } - } - if !matched { - continue - } - - // Found the matching DRM directory - slog.Debug("matched", "amdgpu", match, "drm", devDir) - totalFile := filepath.Join(devDir, DRMTotalMemoryFile) - buf, err := os.ReadFile(totalFile) - if err != nil { - slog.Debug("failed to read sysfs node", "file", totalFile, "error", err) - break - } - totalMemory, err = strconv.ParseUint(strings.TrimSpace(string(buf)), 10, 64) - if err != nil { - slog.Debug("failed to parse sysfs node", "file", totalFile, "error", err) - break - } - - usedFile = filepath.Join(devDir, DRMUsedMemoryFile) - usedMemory, err = getFreeMemory(usedFile) - if err != nil { - slog.Debug("failed to update used memory", "error", err) - } - break - } - - // iGPU detection, remove this check once we can support an iGPU variant of the rocm library - if totalMemory < IGPUMemLimit { - slog.Info("unsupported Radeon iGPU detected skipping", "id", gpuID, "total", format.HumanBytes2(totalMemory)) - continue - } - var name string - // TODO - PCI ID lookup - if vendor > 0 && device > 0 { - name = fmt.Sprintf("%04x:%04x", vendor, device) - } - - slog.Debug("amdgpu memory", "gpu", gpuID, "total", format.HumanBytes2(totalMemory)) - slog.Debug("amdgpu memory", "gpu", gpuID, "available", format.HumanBytes2(totalMemory-usedMemory)) - gpuInfo := RocmGPUInfo{ - GpuInfo: GpuInfo{ - Library: "rocm", - memInfo: memInfo{ - TotalMemory: totalMemory, - FreeMemory: (totalMemory - usedMemory), - }, - ID: strconv.Itoa(gpuID), - Name: name, - Compute: fmt.Sprintf("gfx%d%x%x", major, minor, patch), - MinimumMemory: rocmMinimumMemory, - DriverMajor: driverMajor, - DriverMinor: driverMinor, - }, - usedFilepath: usedFile, - } - - // If the user wants to filter to a subset of devices, filter out if we aren't a match - if len(visibleDevices) > 0 { - include := false - for _, visible := range visibleDevices { - if visible == gpuInfo.ID { - include = true - break - } - } - if !include { - slog.Info("filtering out device per user request", "id", gpuInfo.ID, "visible_devices", visibleDevices) - continue - } - } - - // Final validation is gfx compatibility - load the library if we haven't already loaded it - // even if the user overrides, we still need to validate the library - if libDir == "" { - libDir, err = AMDValidateLibDir() - if err != nil { - slog.Warn("unable to verify rocm library, will use cpu", "error", err) - return nil - } - } - gpuInfo.DependencyPath = libDir - - if gfxOverride == "" { - // Only load supported list once - if len(supported) == 0 { - supported, err = GetSupportedGFX(libDir) - if err != nil { - slog.Warn("failed to lookup supported GFX types, falling back to CPU mode", "error", err) - return nil - } - slog.Debug("rocm supported GPUs", "types", supported) - } - gfx := gpuInfo.Compute - if !slices.Contains[[]string, string](supported, gfx) { - slog.Warn("amdgpu is not supported", "gpu", gpuInfo.ID, "gpu_type", gfx, "library", libDir, "supported_types", supported) - // TODO - consider discrete markdown just for ROCM troubleshooting? - slog.Warn("See https://github.com/ollama/ollama/blob/main/docs/gpu.md#overrides for HSA_OVERRIDE_GFX_VERSION usage") - continue - } else { - slog.Info("amdgpu is supported", "gpu", gpuInfo.ID, "gpu_type", gfx) - } - } else { - slog.Info("skipping rocm gfx compatibility check", "HSA_OVERRIDE_GFX_VERSION", gfxOverride) - } - - // Check for env var workarounds - if name == "1002:687f" { // Vega RX 56 - gpuInfo.EnvWorkarounds = append(gpuInfo.EnvWorkarounds, [2]string{"HSA_ENABLE_SDMA", "0"}) - } - - // The GPU has passed all the verification steps and is supported - resp = append(resp, gpuInfo) - } - if len(resp) == 0 { - slog.Info("no compatible amdgpu devices detected") - } - return resp -} - -// Quick check for AMD driver so we can skip amdgpu discovery if not present -func AMDDetected() bool { - // Some driver versions (older?) don't have a version file, so just lookup the parent dir - sysfsDir := filepath.Dir(DriverVersionFile) - _, err := os.Stat(sysfsDir) - if errors.Is(err, os.ErrNotExist) { - slog.Debug("amdgpu driver not detected " + sysfsDir) - return false - } else if err != nil { - slog.Debug("error looking up amd driver", "path", sysfsDir, "error", err) - return false - } - return true -} - -// Prefer to use host installed ROCm, as long as it meets our minimum requirements -// failing that, tell the user how to download it on their own -func AMDValidateLibDir() (string, error) { - libDir, err := commonAMDValidateLibDir() - if err == nil { - return libDir, nil - } - - // Well known ollama installer path - installedRocmDir := "/usr/share/ollama/lib/rocm" - if rocmLibUsable(installedRocmDir) { - return installedRocmDir, nil - } - - // If we still haven't found a usable rocm, the user will have to install it on their own - slog.Warn("amdgpu detected, but no compatible rocm library found. Either install rocm v6, or follow manual install instructions at https://github.com/ollama/ollama/blob/main/docs/linux.md#manual-install") - return "", errors.New("no suitable rocm found, falling back to CPU") -} - -func AMDDriverVersion() (driverMajor, driverMinor int, err error) { - _, err = os.Stat(DriverVersionFile) - if err != nil { - return 0, 0, fmt.Errorf("amdgpu version file missing: %s %w", DriverVersionFile, err) - } - fp, err := os.Open(DriverVersionFile) - if err != nil { - return 0, 0, err - } - defer fp.Close() - verString, err := io.ReadAll(fp) - if err != nil { - return 0, 0, err - } - - pattern := `\A(\d+)\.(\d+).*` - regex := regexp.MustCompile(pattern) - match := regex.FindStringSubmatch(string(verString)) - if len(match) < 2 { - return 0, 0, fmt.Errorf("malformed version string %s", string(verString)) - } - driverMajor, err = strconv.Atoi(match[1]) - if err != nil { - return 0, 0, err - } - driverMinor, err = strconv.Atoi(match[2]) - if err != nil { - return 0, 0, err - } - return driverMajor, driverMinor, nil -} - -func (gpus RocmGPUInfoList) RefreshFreeMemory() error { - if len(gpus) == 0 { - return nil - } - for i := range gpus { - usedMemory, err := getFreeMemory(gpus[i].usedFilepath) - if err != nil { - return err - } - slog.Debug("updating rocm free memory", "gpu", gpus[i].ID, "name", gpus[i].Name, "before", format.HumanBytes2(gpus[i].FreeMemory), "now", format.HumanBytes2(gpus[i].TotalMemory-usedMemory)) - gpus[i].FreeMemory = gpus[i].TotalMemory - usedMemory - } - return nil -} - -func getFreeMemory(usedFile string) (uint64, error) { - buf, err := os.ReadFile(usedFile) - if err != nil { - return 0, fmt.Errorf("failed to read sysfs node %s %w", usedFile, err) - } - usedMemory, err := strconv.ParseUint(strings.TrimSpace(string(buf)), 10, 64) - if err != nil { - slog.Debug("failed to parse sysfs node", "file", usedFile, "error", err) - return 0, fmt.Errorf("failed to parse sysfs node %s %w", usedFile, err) - } - return usedMemory, nil -} diff --git a/ollama/gpu/amd_windows.go b/ollama/gpu/amd_windows.go deleted file mode 100755 index edabeb4..0000000 --- a/ollama/gpu/amd_windows.go +++ /dev/null @@ -1,192 +0,0 @@ -package gpu - -import ( - "bytes" - "errors" - "log/slog" - "os" - "path/filepath" - "slices" - "strconv" - "strings" - - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/format" -) - -const ( - - // TODO We're lookinng for this exact name to detect iGPUs since hipGetDeviceProperties never reports integrated==true - iGPUName = "AMD Radeon(TM) Graphics" -) - -var ( - // Used to validate if the given ROCm lib is usable - ROCmLibGlobs = []string{"hipblas.dll", "rocblas"} // This is not sufficient to discern v5 vs v6 - RocmStandardLocations = []string{"C:\\Program Files\\AMD\\ROCm\\6.1\\bin"} // TODO glob? -) - -func AMDGetGPUInfo() []RocmGPUInfo { - resp := []RocmGPUInfo{} - hl, err := NewHipLib() - if err != nil { - slog.Debug(err.Error()) - return nil - } - defer hl.Release() - - driverMajor, driverMinor, err := hl.AMDDriverVersion() - if err != nil { - // For now this is benign, but we may eventually need to fail compatibility checks - slog.Debug("error looking up amd driver version", "error", err) - } - - // Note: the HIP library automatically handles subsetting to any HIP_VISIBLE_DEVICES the user specified - count := hl.HipGetDeviceCount() - if count == 0 { - return nil - } - libDir, err := AMDValidateLibDir() - if err != nil { - slog.Warn("unable to verify rocm library, will use cpu", "error", err) - return nil - } - - var supported []string - gfxOverride := envconfig.HsaOverrideGfxVersion() - if gfxOverride == "" { - supported, err = GetSupportedGFX(libDir) - if err != nil { - slog.Warn("failed to lookup supported GFX types, falling back to CPU mode", "error", err) - return nil - } - } else { - slog.Info("skipping rocm gfx compatibility check", "HSA_OVERRIDE_GFX_VERSION", gfxOverride) - } - - slog.Debug("detected hip devices", "count", count) - // TODO how to determine the underlying device ID when visible devices is causing this to subset? - for i := range count { - err = hl.HipSetDevice(i) - if err != nil { - slog.Warn("set device", "id", i, "error", err) - continue - } - - props, err := hl.HipGetDeviceProperties(i) - if err != nil { - slog.Warn("get properties", "id", i, "error", err) - continue - } - n := bytes.IndexByte(props.Name[:], 0) - name := string(props.Name[:n]) - // TODO is UUID actually populated on windows? - // Can luid be used on windows for setting visible devices (and is it actually set?) - n = bytes.IndexByte(props.GcnArchName[:], 0) - gfx := string(props.GcnArchName[:n]) - slog.Debug("hip device", "id", i, "name", name, "gfx", gfx) - // slog.Info(fmt.Sprintf("[%d] Integrated: %d", i, props.iGPU)) // DOESN'T REPORT CORRECTLY! Always 0 - // TODO Why isn't props.iGPU accurate!? - if strings.EqualFold(name, iGPUName) { - slog.Info("unsupported Radeon iGPU detected skipping", "id", i, "name", name, "gfx", gfx) - continue - } - if gfxOverride == "" { - // Strip off Target Features when comparing - if !slices.Contains[[]string, string](supported, strings.Split(gfx, ":")[0]) { - slog.Warn("amdgpu is not supported", "gpu", i, "gpu_type", gfx, "library", libDir, "supported_types", supported) - // TODO - consider discrete markdown just for ROCM troubleshooting? - slog.Warn("See https://github.com/ollama/ollama/blob/main/docs/troubleshooting.md for HSA_OVERRIDE_GFX_VERSION usage") - continue - } else { - slog.Debug("amdgpu is supported", "gpu", i, "gpu_type", gfx) - } - } - - freeMemory, totalMemory, err := hl.HipMemGetInfo() - if err != nil { - slog.Warn("get mem info", "id", i, "error", err) - continue - } - - // iGPU detection, remove this check once we can support an iGPU variant of the rocm library - if totalMemory < IGPUMemLimit { - slog.Info("amdgpu appears to be an iGPU, skipping", "gpu", i, "total", format.HumanBytes2(totalMemory)) - continue - } - - slog.Debug("amdgpu memory", "gpu", i, "total", format.HumanBytes2(totalMemory)) - slog.Debug("amdgpu memory", "gpu", i, "available", format.HumanBytes2(freeMemory)) - gpuInfo := RocmGPUInfo{ - GpuInfo: GpuInfo{ - Library: "rocm", - memInfo: memInfo{ - TotalMemory: totalMemory, - FreeMemory: freeMemory, - }, - // Free memory reporting on Windows is not reliable until we bump to ROCm v6.2 - UnreliableFreeMemory: true, - - ID: strconv.Itoa(i), // TODO this is probably wrong if we specify visible devices - DependencyPath: libDir, - MinimumMemory: rocmMinimumMemory, - Name: name, - Compute: gfx, - DriverMajor: driverMajor, - DriverMinor: driverMinor, - }, - index: i, - } - - resp = append(resp, gpuInfo) - } - - return resp -} - -func AMDValidateLibDir() (string, error) { - libDir, err := commonAMDValidateLibDir() - if err == nil { - return libDir, nil - } - - // Installer payload (if we're running from some other location) - localAppData := os.Getenv("LOCALAPPDATA") - appDir := filepath.Join(localAppData, "Programs", "Ollama") - rocmTargetDir := filepath.Join(appDir, "rocm") - if rocmLibUsable(rocmTargetDir) { - slog.Debug("detected ollama installed ROCm at " + rocmTargetDir) - return rocmTargetDir, nil - } - - // Should not happen on windows since we include it in the installer, but stand-alone binary might hit this - slog.Warn("amdgpu detected, but no compatible rocm library found. Please install ROCm") - return "", errors.New("no suitable rocm found, falling back to CPU") -} - -func (gpus RocmGPUInfoList) RefreshFreeMemory() error { - if len(gpus) == 0 { - return nil - } - hl, err := NewHipLib() - if err != nil { - slog.Debug(err.Error()) - return nil - } - defer hl.Release() - - for i := range gpus { - err := hl.HipSetDevice(gpus[i].index) - if err != nil { - return err - } - freeMemory, _, err := hl.HipMemGetInfo() - if err != nil { - slog.Warn("get mem info", "id", i, "error", err) - continue - } - slog.Debug("updating rocm free memory", "gpu", gpus[i].ID, "name", gpus[i].Name, "before", format.HumanBytes2(gpus[i].FreeMemory), "now", format.HumanBytes2(freeMemory)) - gpus[i].FreeMemory = freeMemory - } - return nil -} diff --git a/ollama/gpu/assets.go b/ollama/gpu/assets.go deleted file mode 100755 index 6d62d0d..0000000 --- a/ollama/gpu/assets.go +++ /dev/null @@ -1,148 +0,0 @@ -package gpu - -import ( - "errors" - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "syscall" - "time" - - "github.com/ollama/ollama/envconfig" -) - -var ( - lock sync.Mutex - payloadsDir = "" -) - -func PayloadsDir() (string, error) { - lock.Lock() - defer lock.Unlock() - var err error - if payloadsDir == "" { - runnersDir := envconfig.RunnersDir() - - if runnersDir != "" { - payloadsDir = runnersDir - return payloadsDir, nil - } - - // The remainder only applies on non-windows where we still carry payloads in the main executable - cleanupTmpDirs() - tmpDir := envconfig.TmpDir() - if tmpDir == "" { - tmpDir, err = os.MkdirTemp("", "ollama") - if err != nil { - return "", fmt.Errorf("failed to generate tmp dir: %w", err) - } - } else { - err = os.MkdirAll(tmpDir, 0o755) - if err != nil { - return "", fmt.Errorf("failed to generate tmp dir %s: %w", tmpDir, err) - } - } - - // Track our pid so we can clean up orphaned tmpdirs - n := filepath.Join(tmpDir, "ollama.pid") - if err := os.WriteFile(n, []byte(strconv.Itoa(os.Getpid())), 0o644); err != nil { - return "", fmt.Errorf("failed to write pid file %s: %w", n, err) - } - - // We create a distinct subdirectory for payloads within the tmpdir - // This will typically look like /tmp/ollama3208993108/runners on linux - payloadsDir = filepath.Join(tmpDir, "runners") - } - return payloadsDir, nil -} - -// Best effort to clean up prior tmpdirs -func cleanupTmpDirs() { - matches, err := filepath.Glob(filepath.Join(os.TempDir(), "ollama*", "ollama.pid")) - if err != nil { - return - } - - for _, match := range matches { - raw, err := os.ReadFile(match) - if errors.Is(err, os.ErrNotExist) { - slog.Debug("not a ollama runtime directory, skipping", "path", match) - continue - } else if err != nil { - slog.Warn("could not read ollama.pid, skipping", "path", match, "error", err) - continue - } - - pid, err := strconv.Atoi(string(raw)) - if err != nil { - slog.Warn("invalid pid, skipping", "path", match, "error", err) - continue - } - - p, err := os.FindProcess(pid) - if err == nil && !errors.Is(p.Signal(syscall.Signal(0)), os.ErrProcessDone) { - slog.Warn("process still running, skipping", "pid", pid, "path", match) - continue - } - - if err := os.Remove(match); err != nil { - slog.Warn("could not cleanup stale pidfile", "path", match, "error", err) - } - - runners := filepath.Join(filepath.Dir(match), "runners") - if err := os.RemoveAll(runners); err != nil { - slog.Warn("could not cleanup stale runners", "path", runners, "error", err) - } - - if err := os.Remove(filepath.Dir(match)); err != nil { - slog.Warn("could not cleanup stale tmpdir", "path", filepath.Dir(match), "error", err) - } - } -} - -func Cleanup() { - lock.Lock() - defer lock.Unlock() - runnersDir := envconfig.RunnersDir() - if payloadsDir != "" && runnersDir == "" && runtime.GOOS != "windows" { - // We want to fully clean up the tmpdir parent of the payloads dir - tmpDir := filepath.Clean(filepath.Join(payloadsDir, "..")) - slog.Debug("cleaning up", "dir", tmpDir) - err := os.RemoveAll(tmpDir) - if err != nil { - // On windows, if we remove too quickly the llama.dll may still be in-use and fail to remove - time.Sleep(1000 * time.Millisecond) - err = os.RemoveAll(tmpDir) - if err != nil { - slog.Warn("failed to clean up", "dir", tmpDir, "err", err) - } - } - } -} - -func UpdatePath(dir string) { - if runtime.GOOS == "windows" { - tmpDir := filepath.Dir(dir) - pathComponents := strings.Split(os.Getenv("PATH"), ";") - i := 0 - for _, comp := range pathComponents { - if strings.EqualFold(comp, dir) { - return - } - // Remove any other prior paths to our temp dir - if !strings.HasPrefix(strings.ToLower(comp), strings.ToLower(tmpDir)) { - pathComponents[i] = comp - i++ - } - } - newPath := strings.Join(append([]string{dir}, pathComponents...), ";") - slog.Info("updating", "PATH", newPath) - os.Setenv("PATH", newPath) - } - // linux and darwin rely on rpath -} diff --git a/ollama/gpu/cpu_common.go b/ollama/gpu/cpu_common.go deleted file mode 100755 index 34edcdc..0000000 --- a/ollama/gpu/cpu_common.go +++ /dev/null @@ -1,37 +0,0 @@ -package gpu - -import ( - "os" - "path/filepath" - "runtime" - "strings" - - "golang.org/x/sys/cpu" -) - -func GetCPUCapability() CPUCapability { - if cpu.X86.HasAVX2 { - return CPUCapabilityAVX2 - } - if cpu.X86.HasAVX { - return CPUCapabilityAVX - } - // else LCD - return CPUCapabilityNone -} - -func IsNUMA() bool { - if runtime.GOOS != "linux" { - // numa support in llama.cpp is linux only - return false - } - ids := map[string]interface{}{} - packageIds, _ := filepath.Glob("/sys/devices/system/cpu/cpu*/topology/physical_package_id") - for _, packageId := range packageIds { - id, err := os.ReadFile(packageId) - if err == nil { - ids[strings.TrimSpace(string(id))] = struct{}{} - } - } - return len(ids) > 1 -} diff --git a/ollama/gpu/cuda_common.go b/ollama/gpu/cuda_common.go deleted file mode 100755 index c90a644..0000000 --- a/ollama/gpu/cuda_common.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build linux || windows - -package gpu - -import ( - "log/slog" - "strings" -) - -func cudaGetVisibleDevicesEnv(gpuInfo []GpuInfo) (string, string) { - ids := []string{} - for _, info := range gpuInfo { - if info.Library != "cuda" { - // TODO shouldn't happen if things are wired correctly... - slog.Debug("cudaGetVisibleDevicesEnv skipping over non-cuda device", "library", info.Library) - continue - } - ids = append(ids, info.ID) - } - return "CUDA_VISIBLE_DEVICES", strings.Join(ids, ",") -} diff --git a/ollama/gpu/gpu.go b/ollama/gpu/gpu.go deleted file mode 100755 index dc124a3..0000000 --- a/ollama/gpu/gpu.go +++ /dev/null @@ -1,643 +0,0 @@ -//go:build linux || windows - -package gpu - -/* -#cgo linux LDFLAGS: -lrt -lpthread -ldl -lstdc++ -lm -#cgo windows LDFLAGS: -lpthread - -#include "gpu_info.h" -*/ -import "C" - -import ( - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - "strings" - "sync" - "unsafe" - - "github.com/ollama/ollama/envconfig" - "github.com/ollama/ollama/format" -) - -type cudaHandles struct { - deviceCount int - cudart *C.cudart_handle_t - nvcuda *C.nvcuda_handle_t - nvml *C.nvml_handle_t -} - -type oneapiHandles struct { - oneapi *C.oneapi_handle_t - deviceCount int -} - -const ( - cudaMinimumMemory = 457 * format.MebiByte - rocmMinimumMemory = 457 * format.MebiByte - // TODO OneAPI minimum memory -) - -var ( - gpuMutex sync.Mutex - bootstrapped bool - cpuCapability CPUCapability - cpus []CPUInfo - cudaGPUs []CudaGPUInfo - nvcudaLibPath string - cudartLibPath string - oneapiLibPath string - nvmlLibPath string - rocmGPUs []RocmGPUInfo - oneapiGPUs []OneapiGPUInfo -) - -// With our current CUDA compile flags, older than 5.0 will not work properly -var CudaComputeMin = [2]C.int{5, 0} - -var RocmComputeMin = 9 - -// TODO find a better way to detect iGPU instead of minimum memory -const IGPUMemLimit = 1 * format.GibiByte // 512G is what they typically report, so anything less than 1G must be iGPU - -// Jetson devices have JETSON_JETPACK="x.y.z" factory set to the Jetpack version installed. -// Included to drive logic for reducing Ollama-allocated overhead on L4T/Jetson devices. -var CudaTegra string = os.Getenv("JETSON_JETPACK") - -// Note: gpuMutex must already be held -func initCudaHandles() *cudaHandles { - // TODO - if the ollama build is CPU only, don't do these checks as they're irrelevant and confusing - - cHandles := &cudaHandles{} - // Short Circuit if we already know which library to use - if nvmlLibPath != "" { - cHandles.nvml, _ = LoadNVMLMgmt([]string{nvmlLibPath}) - return cHandles - } - if nvcudaLibPath != "" { - cHandles.deviceCount, cHandles.nvcuda, _ = LoadNVCUDAMgmt([]string{nvcudaLibPath}) - return cHandles - } - if cudartLibPath != "" { - cHandles.deviceCount, cHandles.cudart, _ = LoadCUDARTMgmt([]string{cudartLibPath}) - return cHandles - } - - slog.Debug("searching for GPU discovery libraries for NVIDIA") - var cudartMgmtPatterns []string - - // Aligned with driver, we can't carry as payloads - nvcudaMgmtPatterns := NvcudaGlobs - - if runtime.GOOS == "windows" { - localAppData := os.Getenv("LOCALAPPDATA") - cudartMgmtPatterns = []string{filepath.Join(localAppData, "Programs", "Ollama", CudartMgmtName)} - } - tmpDir, _ := PayloadsDir() - if tmpDir != "" { - // TODO - add "payloads" for subprocess - cudartMgmtPatterns = []string{filepath.Join(tmpDir, "cuda*", CudartMgmtName)} - } - cudartMgmtPatterns = append(cudartMgmtPatterns, CudartGlobs...) - - if len(NvmlGlobs) > 0 { - nvmlLibPaths := FindGPULibs(NvmlMgmtName, NvmlGlobs) - if len(nvmlLibPaths) > 0 { - nvml, libPath := LoadNVMLMgmt(nvmlLibPaths) - if nvml != nil { - slog.Debug("nvidia-ml loaded", "library", libPath) - cHandles.nvml = nvml - nvmlLibPath = libPath - } - } - } - - nvcudaLibPaths := FindGPULibs(NvcudaMgmtName, nvcudaMgmtPatterns) - if len(nvcudaLibPaths) > 0 { - deviceCount, nvcuda, libPath := LoadNVCUDAMgmt(nvcudaLibPaths) - if nvcuda != nil { - slog.Debug("detected GPUs", "count", deviceCount, "library", libPath) - cHandles.nvcuda = nvcuda - cHandles.deviceCount = deviceCount - nvcudaLibPath = libPath - return cHandles - } - } - - cudartLibPaths := FindGPULibs(CudartMgmtName, cudartMgmtPatterns) - if len(cudartLibPaths) > 0 { - deviceCount, cudart, libPath := LoadCUDARTMgmt(cudartLibPaths) - if cudart != nil { - slog.Debug("detected GPUs", "library", libPath, "count", deviceCount) - cHandles.cudart = cudart - cHandles.deviceCount = deviceCount - cudartLibPath = libPath - return cHandles - } - } - - return cHandles -} - -// Note: gpuMutex must already be held -func initOneAPIHandles() *oneapiHandles { - oHandles := &oneapiHandles{} - - // Short Circuit if we already know which library to use - if oneapiLibPath != "" { - oHandles.deviceCount, oHandles.oneapi, _ = LoadOneapiMgmt([]string{oneapiLibPath}) - return oHandles - } - - oneapiLibPaths := FindGPULibs(OneapiMgmtName, OneapiGlobs) - if len(oneapiLibPaths) > 0 { - oHandles.deviceCount, oHandles.oneapi, oneapiLibPath = LoadOneapiMgmt(oneapiLibPaths) - } - - return oHandles -} - -func GetCPUInfo() GpuInfoList { - gpuMutex.Lock() - if !bootstrapped { - gpuMutex.Unlock() - GetGPUInfo() - } else { - gpuMutex.Unlock() - } - return GpuInfoList{cpus[0].GpuInfo} -} - -func GetGPUInfo() GpuInfoList { - // TODO - consider exploring lspci (and equivalent on windows) to check for - // GPUs so we can report warnings if we see Nvidia/AMD but fail to load the libraries - gpuMutex.Lock() - defer gpuMutex.Unlock() - needRefresh := true - var cHandles *cudaHandles - var oHandles *oneapiHandles - defer func() { - if cHandles != nil { - if cHandles.cudart != nil { - C.cudart_release(*cHandles.cudart) - } - if cHandles.nvcuda != nil { - C.nvcuda_release(*cHandles.nvcuda) - } - if cHandles.nvml != nil { - C.nvml_release(*cHandles.nvml) - } - } - if oHandles != nil { - if oHandles.oneapi != nil { - // TODO - is this needed? - C.oneapi_release(*oHandles.oneapi) - } - } - }() - - if !bootstrapped { - slog.Info("looking for compatible GPUs") - needRefresh = false - cpuCapability = GetCPUCapability() - var memInfo C.mem_info_t - - mem, err := GetCPUMem() - if err != nil { - slog.Warn("error looking up system memory", "error", err) - } - cpus = []CPUInfo{ - { - GpuInfo: GpuInfo{ - memInfo: mem, - Library: "cpu", - Variant: cpuCapability, - ID: "0", - }, - }, - } - - // Fallback to CPU mode if we're lacking required vector extensions on x86 - if cpuCapability < GPURunnerCPUCapability && runtime.GOARCH == "amd64" { - slog.Warn("CPU does not have minimum vector extensions, GPU inference disabled", "required", GPURunnerCPUCapability, "detected", cpuCapability) - bootstrapped = true - // No need to do any GPU discovery, since we can't run on them - return GpuInfoList{cpus[0].GpuInfo} - } - - // On windows we bundle the nvidia library one level above the runner dir - depPath := "" - if runtime.GOOS == "windows" && envconfig.RunnersDir() != "" { - depPath = filepath.Join(filepath.Dir(envconfig.RunnersDir()), "cuda") - } - - // Load ALL libraries - cHandles = initCudaHandles() - - // NVIDIA - for i := range cHandles.deviceCount { - if cHandles.cudart != nil || cHandles.nvcuda != nil { - gpuInfo := CudaGPUInfo{ - GpuInfo: GpuInfo{ - Library: "cuda", - }, - index: i, - } - var driverMajor int - var driverMinor int - if cHandles.cudart != nil { - C.cudart_bootstrap(*cHandles.cudart, C.int(i), &memInfo) - } else { - C.nvcuda_bootstrap(*cHandles.nvcuda, C.int(i), &memInfo) - driverMajor = int(cHandles.nvcuda.driver_major) - driverMinor = int(cHandles.nvcuda.driver_minor) - } - if memInfo.err != nil { - slog.Info("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err)) - C.free(unsafe.Pointer(memInfo.err)) - continue - } - if memInfo.major < CudaComputeMin[0] || (memInfo.major == CudaComputeMin[0] && memInfo.minor < CudaComputeMin[1]) { - slog.Info(fmt.Sprintf("[%d] CUDA GPU is too old. Compute Capability detected: %d.%d", i, memInfo.major, memInfo.minor)) - continue - } - gpuInfo.TotalMemory = uint64(memInfo.total) - gpuInfo.FreeMemory = uint64(memInfo.free) - gpuInfo.ID = C.GoString(&memInfo.gpu_id[0]) - gpuInfo.Compute = fmt.Sprintf("%d.%d", memInfo.major, memInfo.minor) - gpuInfo.MinimumMemory = cudaMinimumMemory - gpuInfo.DependencyPath = depPath - gpuInfo.Name = C.GoString(&memInfo.gpu_name[0]) - gpuInfo.DriverMajor = driverMajor - gpuInfo.DriverMinor = driverMinor - - // query the management library as well so we can record any skew between the two - // which represents overhead on the GPU we must set aside on subsequent updates - if cHandles.nvml != nil { - C.nvml_get_free(*cHandles.nvml, C.int(gpuInfo.index), &memInfo.free, &memInfo.total, &memInfo.used) - if memInfo.err != nil { - slog.Warn("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err)) - C.free(unsafe.Pointer(memInfo.err)) - } else { - if memInfo.free != 0 && uint64(memInfo.free) > gpuInfo.FreeMemory { - gpuInfo.OSOverhead = uint64(memInfo.free) - gpuInfo.FreeMemory - slog.Info("detected OS VRAM overhead", - "id", gpuInfo.ID, - "library", gpuInfo.Library, - "compute", gpuInfo.Compute, - "driver", fmt.Sprintf("%d.%d", gpuInfo.DriverMajor, gpuInfo.DriverMinor), - "name", gpuInfo.Name, - "overhead", format.HumanBytes2(gpuInfo.OSOverhead), - ) - } - } - } - - // TODO potentially sort on our own algorithm instead of what the underlying GPU library does... - cudaGPUs = append(cudaGPUs, gpuInfo) - } - } - - // Intel - if envconfig.IntelGPU() { - oHandles = initOneAPIHandles() - if oHandles != nil && oHandles.oneapi != nil { - - // On windows we bundle the oneapi library one level above the runner dir - depPath = "" - if runtime.GOOS == "windows" && envconfig.RunnersDir() != "" { - depPath = filepath.Join(filepath.Dir(envconfig.RunnersDir()), "oneapi") - } - - for d := range oHandles.oneapi.num_drivers { - if oHandles.oneapi == nil { - // shouldn't happen - slog.Warn("nil oneapi handle with driver count", "count", int(oHandles.oneapi.num_drivers)) - continue - } - devCount := C.oneapi_get_device_count(*oHandles.oneapi, C.int(d)) - for i := range devCount { - gpuInfo := OneapiGPUInfo{ - GpuInfo: GpuInfo{ - Library: "oneapi", - }, - driverIndex: int(d), - gpuIndex: int(i), - } - // TODO - split bootstrapping from updating free memory - C.oneapi_check_vram(*oHandles.oneapi, C.int(d), i, &memInfo) - // TODO - convert this to MinimumMemory based on testing... - var totalFreeMem float64 = float64(memInfo.free) * 0.95 // work-around: leave some reserve vram for mkl lib used in ggml-sycl backend. - memInfo.free = C.uint64_t(totalFreeMem) - gpuInfo.TotalMemory = uint64(memInfo.total) - gpuInfo.FreeMemory = uint64(memInfo.free) - gpuInfo.ID = C.GoString(&memInfo.gpu_id[0]) - gpuInfo.Name = C.GoString(&memInfo.gpu_name[0]) - gpuInfo.DependencyPath = depPath - oneapiGPUs = append(oneapiGPUs, gpuInfo) - } - } - } - } - - rocmGPUs = AMDGetGPUInfo() - bootstrapped = true - if len(cudaGPUs) == 0 && len(rocmGPUs) == 0 && len(oneapiGPUs) == 0 { - slog.Info("no compatible GPUs were discovered") - } - } - - // For detected GPUs, load library if not loaded - - // Refresh free memory usage - if needRefresh { - mem, err := GetCPUMem() - if err != nil { - slog.Warn("error looking up system memory", "error", err) - } else { - slog.Debug("updating system memory data", - slog.Group( - "before", - "total", format.HumanBytes2(cpus[0].TotalMemory), - "free", format.HumanBytes2(cpus[0].FreeMemory), - "free_swap", format.HumanBytes2(cpus[0].FreeSwap), - ), - slog.Group( - "now", - "total", format.HumanBytes2(mem.TotalMemory), - "free", format.HumanBytes2(mem.FreeMemory), - "free_swap", format.HumanBytes2(mem.FreeSwap), - ), - ) - cpus[0].FreeMemory = mem.FreeMemory - cpus[0].FreeSwap = mem.FreeSwap - } - - var memInfo C.mem_info_t - if cHandles == nil && len(cudaGPUs) > 0 { - cHandles = initCudaHandles() - } - for i, gpu := range cudaGPUs { - if cHandles.nvml != nil { - C.nvml_get_free(*cHandles.nvml, C.int(gpu.index), &memInfo.free, &memInfo.total, &memInfo.used) - } else if cHandles.cudart != nil { - C.cudart_bootstrap(*cHandles.cudart, C.int(gpu.index), &memInfo) - } else if cHandles.nvcuda != nil { - C.nvcuda_get_free(*cHandles.nvcuda, C.int(gpu.index), &memInfo.free, &memInfo.total) - memInfo.used = memInfo.total - memInfo.free - } else { - // shouldn't happen - slog.Warn("no valid cuda library loaded to refresh vram usage") - break - } - if memInfo.err != nil { - slog.Warn("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err)) - C.free(unsafe.Pointer(memInfo.err)) - continue - } - if memInfo.free == 0 { - slog.Warn("error looking up nvidia GPU memory") - continue - } - if cHandles.nvml != nil && gpu.OSOverhead > 0 { - // When using the management library update based on recorded overhead - memInfo.free -= C.uint64_t(gpu.OSOverhead) - } - slog.Debug("updating cuda memory data", - "gpu", gpu.ID, - "name", gpu.Name, - "overhead", format.HumanBytes2(gpu.OSOverhead), - slog.Group( - "before", - "total", format.HumanBytes2(gpu.TotalMemory), - "free", format.HumanBytes2(gpu.FreeMemory), - ), - slog.Group( - "now", - "total", format.HumanBytes2(uint64(memInfo.total)), - "free", format.HumanBytes2(uint64(memInfo.free)), - "used", format.HumanBytes2(uint64(memInfo.used)), - ), - ) - cudaGPUs[i].FreeMemory = uint64(memInfo.free) - } - - if oHandles == nil && len(oneapiGPUs) > 0 { - oHandles = initOneAPIHandles() - } - for i, gpu := range oneapiGPUs { - if oHandles.oneapi == nil { - // shouldn't happen - slog.Warn("nil oneapi handle with device count", "count", oHandles.deviceCount) - continue - } - C.oneapi_check_vram(*oHandles.oneapi, C.int(gpu.driverIndex), C.int(gpu.gpuIndex), &memInfo) - // TODO - convert this to MinimumMemory based on testing... - var totalFreeMem float64 = float64(memInfo.free) * 0.95 // work-around: leave some reserve vram for mkl lib used in ggml-sycl backend. - memInfo.free = C.uint64_t(totalFreeMem) - oneapiGPUs[i].FreeMemory = uint64(memInfo.free) - } - - err = RocmGPUInfoList(rocmGPUs).RefreshFreeMemory() - if err != nil { - slog.Debug("problem refreshing ROCm free memory", "error", err) - } - } - - resp := []GpuInfo{} - for _, gpu := range cudaGPUs { - resp = append(resp, gpu.GpuInfo) - } - for _, gpu := range rocmGPUs { - resp = append(resp, gpu.GpuInfo) - } - for _, gpu := range oneapiGPUs { - resp = append(resp, gpu.GpuInfo) - } - if len(resp) == 0 { - resp = append(resp, cpus[0].GpuInfo) - } - return resp -} - -func FindGPULibs(baseLibName string, defaultPatterns []string) []string { - // Multiple GPU libraries may exist, and some may not work, so keep trying until we exhaust them - var ldPaths []string - var patterns []string - gpuLibPaths := []string{} - slog.Debug("Searching for GPU library", "name", baseLibName) - - switch runtime.GOOS { - case "windows": - ldPaths = strings.Split(os.Getenv("PATH"), ";") - case "linux": - ldPaths = strings.Split(os.Getenv("LD_LIBRARY_PATH"), ":") - default: - return gpuLibPaths - } - // Start with whatever we find in the PATH/LD_LIBRARY_PATH - for _, ldPath := range ldPaths { - d, err := filepath.Abs(ldPath) - if err != nil { - continue - } - patterns = append(patterns, filepath.Join(d, baseLibName+"*")) - } - patterns = append(patterns, defaultPatterns...) - slog.Debug("gpu library search", "globs", patterns) - for _, pattern := range patterns { - - // Nvidia PhysX known to return bogus results - if strings.Contains(pattern, "PhysX") { - slog.Debug("skipping PhysX cuda library path", "path", pattern) - continue - } - // Ignore glob discovery errors - matches, _ := filepath.Glob(pattern) - for _, match := range matches { - // Resolve any links so we don't try the same lib multiple times - // and weed out any dups across globs - libPath := match - tmp := match - var err error - for ; err == nil; tmp, err = os.Readlink(libPath) { - if !filepath.IsAbs(tmp) { - tmp = filepath.Join(filepath.Dir(libPath), tmp) - } - libPath = tmp - } - new := true - for _, cmp := range gpuLibPaths { - if cmp == libPath { - new = false - break - } - } - if new { - gpuLibPaths = append(gpuLibPaths, libPath) - } - } - } - slog.Debug("discovered GPU libraries", "paths", gpuLibPaths) - return gpuLibPaths -} - -func LoadCUDARTMgmt(cudartLibPaths []string) (int, *C.cudart_handle_t, string) { - var resp C.cudart_init_resp_t - resp.ch.verbose = getVerboseState() - for _, libPath := range cudartLibPaths { - lib := C.CString(libPath) - defer C.free(unsafe.Pointer(lib)) - C.cudart_init(lib, &resp) - if resp.err != nil { - slog.Debug("Unable to load cudart", "library", libPath, "error", C.GoString(resp.err)) - C.free(unsafe.Pointer(resp.err)) - } else { - return int(resp.num_devices), &resp.ch, libPath - } - } - return 0, nil, "" -} - -func LoadNVCUDAMgmt(nvcudaLibPaths []string) (int, *C.nvcuda_handle_t, string) { - var resp C.nvcuda_init_resp_t - resp.ch.verbose = getVerboseState() - for _, libPath := range nvcudaLibPaths { - lib := C.CString(libPath) - defer C.free(unsafe.Pointer(lib)) - C.nvcuda_init(lib, &resp) - if resp.err != nil { - // Decide what log level based on the type of error message to help users understand why - msg := C.GoString(resp.err) - switch resp.cudaErr { - case C.CUDA_ERROR_INSUFFICIENT_DRIVER, C.CUDA_ERROR_SYSTEM_DRIVER_MISMATCH: - slog.Warn("version mismatch between driver and cuda driver library - reboot or upgrade may be required", "library", libPath, "error", msg) - case C.CUDA_ERROR_NO_DEVICE: - slog.Info("no nvidia devices detected", "library", libPath) - case C.CUDA_ERROR_UNKNOWN: - slog.Warn("unknown error initializing cuda driver library", "library", libPath, "error", msg) - slog.Warn("see https://github.com/ollama/ollama/blob/main/docs/troubleshooting.md for more information") - default: - if strings.Contains(msg, "wrong ELF class") { - slog.Debug("skipping 32bit library", "library", libPath) - } else { - slog.Info("unable to load cuda driver library", "library", libPath, "error", msg) - } - } - C.free(unsafe.Pointer(resp.err)) - } else { - return int(resp.num_devices), &resp.ch, libPath - } - } - return 0, nil, "" -} - -func LoadNVMLMgmt(nvmlLibPaths []string) (*C.nvml_handle_t, string) { - var resp C.nvml_init_resp_t - resp.ch.verbose = getVerboseState() - for _, libPath := range nvmlLibPaths { - lib := C.CString(libPath) - defer C.free(unsafe.Pointer(lib)) - C.nvml_init(lib, &resp) - if resp.err != nil { - slog.Info(fmt.Sprintf("Unable to load NVML management library %s: %s", libPath, C.GoString(resp.err))) - C.free(unsafe.Pointer(resp.err)) - } else { - return &resp.ch, libPath - } - } - return nil, "" -} - -func LoadOneapiMgmt(oneapiLibPaths []string) (int, *C.oneapi_handle_t, string) { - var resp C.oneapi_init_resp_t - num_devices := 0 - resp.oh.verbose = getVerboseState() - for _, libPath := range oneapiLibPaths { - lib := C.CString(libPath) - defer C.free(unsafe.Pointer(lib)) - C.oneapi_init(lib, &resp) - if resp.err != nil { - slog.Debug("Unable to load oneAPI management library", "library", libPath, "error", C.GoString(resp.err)) - C.free(unsafe.Pointer(resp.err)) - } else { - for i := range resp.oh.num_drivers { - num_devices += int(C.oneapi_get_device_count(resp.oh, C.int(i))) - } - return num_devices, &resp.oh, libPath - } - } - return 0, nil, "" -} - -func getVerboseState() C.uint16_t { - if envconfig.Debug() { - return C.uint16_t(1) - } - return C.uint16_t(0) -} - -// Given the list of GPUs this instantiation is targeted for, -// figure out the visible devices environment variable -// -// If different libraries are detected, the first one is what we use -func (l GpuInfoList) GetVisibleDevicesEnv() (string, string) { - if len(l) == 0 { - return "", "" - } - switch l[0].Library { - case "cuda": - return cudaGetVisibleDevicesEnv(l) - case "rocm": - return rocmGetVisibleDevicesEnv(l) - case "oneapi": - return oneapiGetVisibleDevicesEnv(l) - default: - slog.Debug("no filter required for library " + l[0].Library) - return "", "" - } -} diff --git a/ollama/gpu/gpu_darwin.go b/ollama/gpu/gpu_darwin.go deleted file mode 100755 index 9d9fd84..0000000 --- a/ollama/gpu/gpu_darwin.go +++ /dev/null @@ -1,68 +0,0 @@ -//go:build darwin - -package gpu - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework CoreGraphics -framework Metal -#include "gpu_info_darwin.h" -*/ -import "C" - -import ( - "runtime" - - "github.com/ollama/ollama/format" -) - -const ( - metalMinimumMemory = 512 * format.MebiByte -) - -func GetGPUInfo() GpuInfoList { - mem, _ := GetCPUMem() - if runtime.GOARCH == "amd64" { - return []GpuInfo{ - { - Library: "cpu", - Variant: GetCPUCapability(), - memInfo: mem, - }, - } - } - info := GpuInfo{ - Library: "metal", - ID: "0", - } - info.TotalMemory = uint64(C.getRecommendedMaxVRAM()) - - // TODO is there a way to gather actual allocated video memory? (currentAllocatedSize doesn't work) - info.FreeMemory = info.TotalMemory - - info.MinimumMemory = metalMinimumMemory - return []GpuInfo{info} -} - -func GetCPUInfo() GpuInfoList { - mem, _ := GetCPUMem() - return []GpuInfo{ - { - Library: "cpu", - Variant: GetCPUCapability(), - memInfo: mem, - }, - } -} - -func GetCPUMem() (memInfo, error) { - return memInfo{ - TotalMemory: uint64(C.getPhysicalMemory()), - FreeMemory: uint64(C.getFreeMemory()), - // FreeSwap omitted as Darwin uses dynamic paging - }, nil -} - -func (l GpuInfoList) GetVisibleDevicesEnv() (string, string) { - // No-op on darwin - return "", "" -} diff --git a/ollama/gpu/gpu_info.h b/ollama/gpu/gpu_info.h deleted file mode 100755 index 094b791..0000000 --- a/ollama/gpu/gpu_info.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __APPLE__ -#ifndef __GPU_INFO_H__ -#define __GPU_INFO_H__ -#include -#include -#include - -#ifndef _WIN32 -#include -#define LOAD_LIBRARY(lib, flags) dlopen(lib, flags) -#define LOAD_SYMBOL(handle, sym) dlsym(handle, sym) -#define LOAD_ERR() strdup(dlerror()) -#define UNLOAD_LIBRARY(handle) dlclose(handle) -#else -#include -#define LOAD_LIBRARY(lib, flags) LoadLibrary(lib) -#define LOAD_SYMBOL(handle, sym) GetProcAddress(handle, sym) -#define UNLOAD_LIBRARY(handle) FreeLibrary(handle) -#define LOAD_ERR() ({\ - LPSTR messageBuffer = NULL; \ - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \ - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); \ - char *resp = strdup(messageBuffer); \ - LocalFree(messageBuffer); \ - resp; \ -}) - -#endif - -#define LOG(verbose, ...) \ - do { \ - if (verbose) { \ - fprintf(stderr, __VA_ARGS__); \ - } \ - } while (0) - -#ifdef __cplusplus -extern "C" { -#endif - -#define GPU_ID_LEN 64 -#define GPU_NAME_LEN 96 - -typedef struct mem_info { - char *err; // If non-nill, caller responsible for freeing - char gpu_id[GPU_ID_LEN]; - char gpu_name[GPU_NAME_LEN]; - uint64_t total; - uint64_t free; - uint64_t used; - - // Compute Capability - int major; - int minor; - int patch; -} mem_info_t; - -void cpu_check_ram(mem_info_t *resp); - -#ifdef __cplusplus -} -#endif - -#include "gpu_info_cudart.h" -#include "gpu_info_nvcuda.h" -#include "gpu_info_nvml.h" -#include "gpu_info_oneapi.h" - -#endif // __GPU_INFO_H__ -#endif // __APPLE__ diff --git a/ollama/gpu/gpu_info_cudart.c b/ollama/gpu/gpu_info_cudart.c deleted file mode 100755 index 03f15a2..0000000 --- a/ollama/gpu/gpu_info_cudart.c +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef __APPLE__ // TODO - maybe consider nvidia support on intel macs? - -#include -#include "gpu_info_cudart.h" - -void cudart_init(char *cudart_lib_path, cudart_init_resp_t *resp) { - cudartReturn_t ret; - resp->err = NULL; - resp->num_devices = 0; - const int buflen = 256; - char buf[buflen + 1]; - int i; - - struct lookup { - char *s; - void **p; - } l[] = { - {"cudaSetDevice", (void *)&resp->ch.cudaSetDevice}, - {"cudaDeviceSynchronize", (void *)&resp->ch.cudaDeviceSynchronize}, - {"cudaDeviceReset", (void *)&resp->ch.cudaDeviceReset}, - {"cudaMemGetInfo", (void *)&resp->ch.cudaMemGetInfo}, - {"cudaGetDeviceCount", (void *)&resp->ch.cudaGetDeviceCount}, - {"cudaDeviceGetAttribute", (void *)&resp->ch.cudaDeviceGetAttribute}, - {"cudaDriverGetVersion", (void *)&resp->ch.cudaDriverGetVersion}, - {"cudaGetDeviceProperties", (void *)&resp->ch.cudaGetDeviceProperties}, - {NULL, NULL}, - }; - - resp->ch.handle = LOAD_LIBRARY(cudart_lib_path, RTLD_LAZY); - if (!resp->ch.handle) { - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "library %s load err: %s\n", cudart_lib_path, msg); - snprintf(buf, buflen, - "Unable to load %s library to query for Nvidia GPUs: %s", - cudart_lib_path, msg); - free(msg); - resp->err = strdup(buf); - return; - } - - for (i = 0; l[i].s != NULL; i++) { - *l[i].p = LOAD_SYMBOL(resp->ch.handle, l[i].s); - if (!*(l[i].p)) { - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "dlerr: %s\n", msg); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "symbol lookup for %s failed: %s", l[i].s, - msg); - free(msg); - resp->err = strdup(buf); - return; - } - } - - ret = (*resp->ch.cudaSetDevice)(0); - if (ret != CUDART_SUCCESS) { - LOG(resp->ch.verbose, "cudaSetDevice err: %d\n", ret); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - if (ret == CUDA_ERROR_INSUFFICIENT_DRIVER) { - resp->err = strdup("your nvidia driver is too old or missing. If you have a CUDA GPU please upgrade to run ollama"); - return; - } - snprintf(buf, buflen, "cudart init failure: %d", ret); - resp->err = strdup(buf); - return; - } - - int version = 0; - cudartDriverVersion_t driverVersion; - driverVersion.major = 0; - driverVersion.minor = 0; - - // Report driver version if we're in verbose mode, ignore errors - ret = (*resp->ch.cudaDriverGetVersion)(&version); - if (ret != CUDART_SUCCESS) { - LOG(resp->ch.verbose, "cudaDriverGetVersion failed: %d\n", ret); - } else { - driverVersion.major = version / 1000; - driverVersion.minor = (version - (driverVersion.major * 1000)) / 10; - LOG(resp->ch.verbose, "CUDA driver version: %d-%d\n", driverVersion.major, driverVersion.minor); - } - - ret = (*resp->ch.cudaGetDeviceCount)(&resp->num_devices); - if (ret != CUDART_SUCCESS) { - LOG(resp->ch.verbose, "cudaGetDeviceCount err: %d\n", ret); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "unable to get device count: %d", ret); - resp->err = strdup(buf); - return; - } -} - - -void cudart_bootstrap(cudart_handle_t h, int i, mem_info_t *resp) { - resp->err = NULL; - cudartMemory_t memInfo = {0,0,0}; - cudartReturn_t ret; - const int buflen = 256; - char buf[buflen + 1]; - - if (h.handle == NULL) { - resp->err = strdup("cudart handle isn't initialized"); - return; - } - - ret = (*h.cudaSetDevice)(i); - if (ret != CUDART_SUCCESS) { - snprintf(buf, buflen, "cudart device failed to initialize"); - resp->err = strdup(buf); - return; - } - - cudaDeviceProp_t props; - ret = (*h.cudaGetDeviceProperties)(&props, i); - if (ret != CUDART_SUCCESS) { - LOG(h.verbose, "[%d] device properties lookup failure: %d\n", i, ret); - snprintf(&resp->gpu_id[0], GPU_ID_LEN, "%d", i); - resp->major = 0; - resp->minor = 0; - } else { - int allNull = 1; - for (int j = 0; j < 16; j++) { - if (props.uuid.bytes[j] != 0) { - allNull = 0; - break; - } - } - if (allNull != 0) { - snprintf(&resp->gpu_id[0], GPU_ID_LEN, "%d", i); - } else { - // GPU-d110a105-ac29-1d54-7b49-9c90440f215b - snprintf(&resp->gpu_id[0], GPU_ID_LEN, - "GPU-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - props.uuid.bytes[0], - props.uuid.bytes[1], - props.uuid.bytes[2], - props.uuid.bytes[3], - props.uuid.bytes[4], - props.uuid.bytes[5], - props.uuid.bytes[6], - props.uuid.bytes[7], - props.uuid.bytes[8], - props.uuid.bytes[9], - props.uuid.bytes[10], - props.uuid.bytes[11], - props.uuid.bytes[12], - props.uuid.bytes[13], - props.uuid.bytes[14], - props.uuid.bytes[15] - ); - } - resp->major = props.major; - resp->minor = props.minor; - - // TODO add other useful properties from props - } - ret = (*h.cudaMemGetInfo)(&memInfo.free, &memInfo.total); - if (ret != CUDART_SUCCESS) { - snprintf(buf, buflen, "cudart device memory info lookup failure %d", ret); - resp->err = strdup(buf); - return; - } - - resp->total = memInfo.total; - resp->free = memInfo.free; - resp->used = memInfo.used; - - LOG(h.verbose, "[%s] CUDA totalMem %lu\n", resp->gpu_id, resp->total); - LOG(h.verbose, "[%s] CUDA freeMem %lu\n", resp->gpu_id, resp->free); - LOG(h.verbose, "[%s] CUDA usedMem %lu\n", resp->gpu_id, resp->used); - LOG(h.verbose, "[%s] Compute Capability %d.%d\n", resp->gpu_id, resp->major, resp->minor); -} - -void cudart_release(cudart_handle_t h) { - LOG(h.verbose, "releasing cudart library\n"); - UNLOAD_LIBRARY(h.handle); - h.handle = NULL; -} - -#endif // __APPLE__ \ No newline at end of file diff --git a/ollama/gpu/gpu_info_cudart.h b/ollama/gpu/gpu_info_cudart.h deleted file mode 100755 index ff0c0af..0000000 --- a/ollama/gpu/gpu_info_cudart.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __APPLE__ -#ifndef __GPU_INFO_CUDART_H__ -#define __GPU_INFO_CUDART_H__ -#include "gpu_info.h" - -// Just enough typedef's to dlopen/dlsym for memory information -typedef enum cudartReturn_enum { - CUDART_SUCCESS = 0, - CUDART_ERROR_INVALID_VALUE = 1, - CUDART_ERROR_MEMORY_ALLOCATION = 2, - CUDART_ERROR_INSUFFICIENT_DRIVER = 35, - // Other values omitted for now... -} cudartReturn_t; - -typedef enum cudartDeviceAttr_enum { - cudartDevAttrComputeCapabilityMajor = 75, - cudartDevAttrComputeCapabilityMinor = 76, - - // TODO - not yet wired up but may be useful for Jetson or other - // integrated GPU scenarios with shared memory - cudaDevAttrIntegrated = 18 - -} cudartDeviceAttr_t; - -typedef void *cudartDevice_t; // Opaque is sufficient -typedef struct cudartMemory_st { - size_t total; - size_t free; - size_t used; -} cudartMemory_t; - -typedef struct cudartDriverVersion { - int major; - int minor; -} cudartDriverVersion_t; - -typedef struct cudaUUID { - unsigned char bytes[16]; -} cudaUUID_t; -typedef struct cudaDeviceProp { - char name[256]; /**< ASCII string identifying device */ - cudaUUID_t uuid; /**< 16-byte unique identifier */ - char luid[8]; /**< 8-byte locally unique identifier. Value is undefined on TCC and non-Windows platforms */ - unsigned int luidDeviceNodeMask; /**< LUID device node mask. Value is undefined on TCC and non-Windows platforms */ - size_t totalGlobalMem; /**< Global memory available on device in bytes */ - size_t sharedMemPerBlock; /**< Shared memory available per block in bytes */ - int regsPerBlock; /**< 32-bit registers available per block */ - int warpSize; /**< Warp size in threads */ - size_t memPitch; /**< Maximum pitch in bytes allowed by memory copies */ - int maxThreadsPerBlock; /**< Maximum number of threads per block */ - int maxThreadsDim[3]; /**< Maximum size of each dimension of a block */ - int maxGridSize[3]; /**< Maximum size of each dimension of a grid */ - int clockRate; /**< Clock frequency in kilohertz */ - size_t totalConstMem; /**< Constant memory available on device in bytes */ - int major; /**< Major compute capability */ - int minor; /**< Minor compute capability */ - size_t textureAlignment; /**< Alignment requirement for textures */ - size_t texturePitchAlignment; /**< Pitch alignment requirement for texture references bound to pitched memory */ - int deviceOverlap; /**< Device can concurrently copy memory and execute a kernel. Deprecated. Use instead asyncEngineCount. */ - int multiProcessorCount; /**< Number of multiprocessors on device */ - int kernelExecTimeoutEnabled; /**< Specified whether there is a run time limit on kernels */ - int integrated; /**< Device is integrated as opposed to discrete */ - int canMapHostMemory; /**< Device can map host memory with cudaHostAlloc/cudaHostGetDevicePointer */ - int computeMode; /**< Compute mode (See ::cudaComputeMode) */ - int maxTexture1D; /**< Maximum 1D texture size */ - int maxTexture1DMipmap; /**< Maximum 1D mipmapped texture size */ - int maxTexture1DLinear; /**< Deprecated, do not use. Use cudaDeviceGetTexture1DLinearMaxWidth() or cuDeviceGetTexture1DLinearMaxWidth() instead. */ - int maxTexture2D[2]; /**< Maximum 2D texture dimensions */ - int maxTexture2DMipmap[2]; /**< Maximum 2D mipmapped texture dimensions */ - int maxTexture2DLinear[3]; /**< Maximum dimensions (width, height, pitch) for 2D textures bound to pitched memory */ - int maxTexture2DGather[2]; /**< Maximum 2D texture dimensions if texture gather operations have to be performed */ - int maxTexture3D[3]; /**< Maximum 3D texture dimensions */ - int maxTexture3DAlt[3]; /**< Maximum alternate 3D texture dimensions */ - int maxTextureCubemap; /**< Maximum Cubemap texture dimensions */ - int maxTexture1DLayered[2]; /**< Maximum 1D layered texture dimensions */ - int maxTexture2DLayered[3]; /**< Maximum 2D layered texture dimensions */ - int maxTextureCubemapLayered[2];/**< Maximum Cubemap layered texture dimensions */ - int maxSurface1D; /**< Maximum 1D surface size */ - int maxSurface2D[2]; /**< Maximum 2D surface dimensions */ - int maxSurface3D[3]; /**< Maximum 3D surface dimensions */ - int maxSurface1DLayered[2]; /**< Maximum 1D layered surface dimensions */ - int maxSurface2DLayered[3]; /**< Maximum 2D layered surface dimensions */ - int maxSurfaceCubemap; /**< Maximum Cubemap surface dimensions */ - int maxSurfaceCubemapLayered[2];/**< Maximum Cubemap layered surface dimensions */ - size_t surfaceAlignment; /**< Alignment requirements for surfaces */ - int concurrentKernels; /**< Device can possibly execute multiple kernels concurrently */ - int ECCEnabled; /**< Device has ECC support enabled */ - int pciBusID; /**< PCI bus ID of the device */ - int pciDeviceID; /**< PCI device ID of the device */ - int pciDomainID; /**< PCI domain ID of the device */ - int tccDriver; /**< 1 if device is a Tesla device using TCC driver, 0 otherwise */ - int asyncEngineCount; /**< Number of asynchronous engines */ - int unifiedAddressing; /**< Device shares a unified address space with the host */ - int memoryClockRate; /**< Peak memory clock frequency in kilohertz */ - int memoryBusWidth; /**< Global memory bus width in bits */ - int l2CacheSize; /**< Size of L2 cache in bytes */ - int persistingL2CacheMaxSize; /**< Device's maximum l2 persisting lines capacity setting in bytes */ - int maxThreadsPerMultiProcessor;/**< Maximum resident threads per multiprocessor */ - int streamPrioritiesSupported; /**< Device supports stream priorities */ - int globalL1CacheSupported; /**< Device supports caching globals in L1 */ - int localL1CacheSupported; /**< Device supports caching locals in L1 */ - size_t sharedMemPerMultiprocessor; /**< Shared memory available per multiprocessor in bytes */ - int regsPerMultiprocessor; /**< 32-bit registers available per multiprocessor */ - int managedMemory; /**< Device supports allocating managed memory on this system */ - int isMultiGpuBoard; /**< Device is on a multi-GPU board */ - int multiGpuBoardGroupID; /**< Unique identifier for a group of devices on the same multi-GPU board */ - int hostNativeAtomicSupported; /**< Link between the device and the host supports native atomic operations */ - int singleToDoublePrecisionPerfRatio; /**< Ratio of single precision performance (in floating-point operations per second) to double precision performance */ - int pageableMemoryAccess; /**< Device supports coherently accessing pageable memory without calling cudaHostRegister on it */ - int concurrentManagedAccess; /**< Device can coherently access managed memory concurrently with the CPU */ - int computePreemptionSupported; /**< Device supports Compute Preemption */ - int canUseHostPointerForRegisteredMem; /**< Device can access host registered memory at the same virtual address as the CPU */ - int cooperativeLaunch; /**< Device supports launching cooperative kernels via ::cudaLaunchCooperativeKernel */ - int cooperativeMultiDeviceLaunch; /**< Deprecated, cudaLaunchCooperativeKernelMultiDevice is deprecated. */ - size_t sharedMemPerBlockOptin; /**< Per device maximum shared memory per block usable by special opt in */ - int pageableMemoryAccessUsesHostPageTables; /**< Device accesses pageable memory via the host's page tables */ - int directManagedMemAccessFromHost; /**< Host can directly access managed memory on the device without migration. */ - int maxBlocksPerMultiProcessor; /**< Maximum number of resident blocks per multiprocessor */ - int accessPolicyMaxWindowSize; /**< The maximum value of ::cudaAccessPolicyWindow::num_bytes. */ - size_t reservedSharedMemPerBlock; /**< Shared memory reserved by CUDA driver per block in bytes */ - } cudaDeviceProp_t; - -typedef struct cudart_handle { - void *handle; - uint16_t verbose; - cudartReturn_t (*cudaSetDevice)(int device); - cudartReturn_t (*cudaDeviceSynchronize)(void); - cudartReturn_t (*cudaDeviceReset)(void); - cudartReturn_t (*cudaMemGetInfo)(size_t *, size_t *); - cudartReturn_t (*cudaGetDeviceCount)(int *); - cudartReturn_t (*cudaDeviceGetAttribute)(int* value, cudartDeviceAttr_t attr, int device); - cudartReturn_t (*cudaDriverGetVersion) (int *driverVersion); - cudartReturn_t (*cudaGetDeviceProperties) (cudaDeviceProp_t* prop, int device); -} cudart_handle_t; - -typedef struct cudart_init_resp { - char *err; // If err is non-null handle is invalid - cudart_handle_t ch; - int num_devices; -} cudart_init_resp_t; - -void cudart_init(char *cudart_lib_path, cudart_init_resp_t *resp); -void cudart_bootstrap(cudart_handle_t ch, int device_id, mem_info_t *resp); -// TODO - if we keep this library longer term, add cudart_get_free -void cudart_release(cudart_handle_t ch); - -#endif // __GPU_INFO_CUDART_H__ -#endif // __APPLE__ diff --git a/ollama/gpu/gpu_info_darwin.h b/ollama/gpu/gpu_info_darwin.h deleted file mode 100755 index 415e792..0000000 --- a/ollama/gpu/gpu_info_darwin.h +++ /dev/null @@ -1,5 +0,0 @@ -#import -#include -uint64_t getRecommendedMaxVRAM(); -uint64_t getPhysicalMemory(); -uint64_t getFreeMemory(); diff --git a/ollama/gpu/gpu_info_darwin.m b/ollama/gpu/gpu_info_darwin.m deleted file mode 100755 index 5ca139e..0000000 --- a/ollama/gpu/gpu_info_darwin.m +++ /dev/null @@ -1,35 +0,0 @@ -#import -#import -#include "gpu_info_darwin.h" - -uint64_t getRecommendedMaxVRAM() { - id device = MTLCreateSystemDefaultDevice(); - uint64_t result = device.recommendedMaxWorkingSetSize; - CFRelease(device); - return result; -} - -// getPhysicalMemory returns the total physical memory in bytes -uint64_t getPhysicalMemory() { - return [NSProcessInfo processInfo].physicalMemory; -} - -// getFreeMemory returns the total free memory in bytes, including inactive -// memory that can be reclaimed by the system. -uint64_t getFreeMemory() { - mach_port_t host_port = mach_host_self(); - mach_msg_type_number_t host_size = sizeof(vm_statistics64_data_t) / sizeof(integer_t); - vm_size_t pagesize; - vm_statistics64_data_t vm_stat; - - host_page_size(host_port, &pagesize); - if (host_statistics64(host_port, HOST_VM_INFO64, (host_info64_t)&vm_stat, &host_size) != KERN_SUCCESS) { - return 0; - } - - uint64_t free_memory = (uint64_t)vm_stat.free_count * pagesize; - free_memory += (uint64_t)vm_stat.speculative_count * pagesize; - free_memory += (uint64_t)vm_stat.inactive_count * pagesize; - - return free_memory; -} diff --git a/ollama/gpu/gpu_info_nvcuda.c b/ollama/gpu/gpu_info_nvcuda.c deleted file mode 100755 index a1a38bf..0000000 --- a/ollama/gpu/gpu_info_nvcuda.c +++ /dev/null @@ -1,243 +0,0 @@ -#ifndef __APPLE__ // TODO - maybe consider nvidia support on intel macs? - -#include -#include "gpu_info_nvcuda.h" - -void nvcuda_init(char *nvcuda_lib_path, nvcuda_init_resp_t *resp) { - CUresult ret; - resp->err = NULL; - resp->num_devices = 0; - resp->cudaErr = CUDA_SUCCESS; - const int buflen = 256; - char buf[buflen + 1]; - int i; - - struct lookup { - char *s; - void **p; - } l[] = { - - {"cuInit", (void *)&resp->ch.cuInit}, - {"cuDriverGetVersion", (void *)&resp->ch.cuDriverGetVersion}, - {"cuDeviceGetCount", (void *)&resp->ch.cuDeviceGetCount}, - {"cuDeviceGet", (void *)&resp->ch.cuDeviceGet}, - {"cuDeviceGetAttribute", (void *)&resp->ch.cuDeviceGetAttribute}, - {"cuDeviceGetUuid", (void *)&resp->ch.cuDeviceGetUuid}, - {"cuDeviceGetName", (void *)&resp->ch.cuDeviceGetName}, - {"cuCtxCreate_v3", (void *)&resp->ch.cuCtxCreate_v3}, - {"cuMemGetInfo_v2", (void *)&resp->ch.cuMemGetInfo_v2}, - {"cuCtxDestroy", (void *)&resp->ch.cuCtxDestroy}, - {NULL, NULL}, - }; - - resp->ch.handle = LOAD_LIBRARY(nvcuda_lib_path, RTLD_LAZY); - if (!resp->ch.handle) { - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "library %s load err: %s\n", nvcuda_lib_path, msg); - snprintf(buf, buflen, - "Unable to load %s library to query for Nvidia GPUs: %s", - nvcuda_lib_path, msg); - free(msg); - resp->err = strdup(buf); - resp->cudaErr = -1; - return; - } - - for (i = 0; l[i].s != NULL; i++) { - *l[i].p = LOAD_SYMBOL(resp->ch.handle, l[i].s); - if (!*(l[i].p)) { - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "dlerr: %s\n", msg); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "symbol lookup for %s failed: %s", l[i].s, - msg); - free(msg); - resp->err = strdup(buf); - resp->cudaErr = -1; - return; - } - } - - ret = (*resp->ch.cuInit)(0); - if (ret != CUDA_SUCCESS) { - LOG(resp->ch.verbose, "cuInit err: %d\n", ret); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "cuda driver library init failure: %d", ret); - resp->err = strdup(buf); - resp->cudaErr = ret; - return; - } - - int version = 0; - resp->ch.driver_major = 0; - resp->ch.driver_minor = 0; - - // Report driver version if we're in verbose mode, ignore errors - ret = (*resp->ch.cuDriverGetVersion)(&version); - if (ret != CUDA_SUCCESS) { - LOG(resp->ch.verbose, "cuDriverGetVersion failed: %d\n", ret); - } else { - resp->ch.driver_major = version / 1000; - resp->ch.driver_minor = (version - (resp->ch.driver_major * 1000)) / 10; - LOG(resp->ch.verbose, "CUDA driver version: %d.%d\n", resp->ch.driver_major, resp->ch.driver_minor); - } - - ret = (*resp->ch.cuDeviceGetCount)(&resp->num_devices); - if (ret != CUDA_SUCCESS) { - LOG(resp->ch.verbose, "cuDeviceGetCount err: %d\n", ret); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "unable to get device count: %d", ret); - resp->err = strdup(buf); - resp->cudaErr = ret; - return; - } -} - -const int buflen = 256; -void nvcuda_bootstrap(nvcuda_handle_t h, int i, mem_info_t *resp) { - resp->err = NULL; - nvcudaMemory_t memInfo = {0,0}; - CUresult ret; - CUdevice device = -1; - CUcontext ctx = NULL; - char buf[buflen + 1]; - CUuuid uuid = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - - if (h.handle == NULL) { - resp->err = strdup("cuda driver library handle isn't initialized"); - return; - } - - ret = (*h.cuDeviceGet)(&device, i); - if (ret != CUDA_SUCCESS) { - snprintf(buf, buflen, "cuda driver library device failed to initialize"); - resp->err = strdup(buf); - return; - } - - int major = 0; - int minor = 0; - ret = (*h.cuDeviceGetAttribute)(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device); - if (ret != CUDA_SUCCESS) { - LOG(h.verbose, "[%d] device major lookup failure: %d\n", i, ret); - } else { - ret = (*h.cuDeviceGetAttribute)(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device); - if (ret != CUDA_SUCCESS) { - LOG(h.verbose, "[%d] device minor lookup failure: %d\n", i, ret); - } else { - resp->minor = minor; - resp->major = major; - } - } - - ret = (*h.cuDeviceGetUuid)(&uuid, device); - if (ret != CUDA_SUCCESS) { - LOG(h.verbose, "[%d] device uuid lookup failure: %d\n", i, ret); - snprintf(&resp->gpu_id[0], GPU_ID_LEN, "%d", i); - } else { - // GPU-d110a105-ac29-1d54-7b49-9c90440f215b - snprintf(&resp->gpu_id[0], GPU_ID_LEN, - "GPU-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uuid.bytes[0], - uuid.bytes[1], - uuid.bytes[2], - uuid.bytes[3], - uuid.bytes[4], - uuid.bytes[5], - uuid.bytes[6], - uuid.bytes[7], - uuid.bytes[8], - uuid.bytes[9], - uuid.bytes[10], - uuid.bytes[11], - uuid.bytes[12], - uuid.bytes[13], - uuid.bytes[14], - uuid.bytes[15] - ); - } - - ret = (*h.cuDeviceGetName)(&resp->gpu_name[0], GPU_NAME_LEN, device); - if (ret != CUDA_SUCCESS) { - LOG(h.verbose, "[%d] device name lookup failure: %d\n", i, ret); - resp->gpu_name[0] = '\0'; - } - - // To get memory we have to set (and release) a context - ret = (*h.cuCtxCreate_v3)(&ctx, NULL, 0, 0, device); - if (ret != CUDA_SUCCESS) { - snprintf(buf, buflen, "cuda driver library failed to get device context %d", ret); - resp->err = strdup(buf); - return; - } - - ret = (*h.cuMemGetInfo_v2)(&memInfo.free, &memInfo.total); - if (ret != CUDA_SUCCESS) { - snprintf(buf, buflen, "cuda driver library device memory info lookup failure %d", ret); - resp->err = strdup(buf); - // Best effort on failure... - (*h.cuCtxDestroy)(ctx); - return; - } - - resp->total = memInfo.total; - resp->free = memInfo.free; - - LOG(h.verbose, "[%s] CUDA totalMem %lu mb\n", resp->gpu_id, resp->total / 1024 / 1024); - LOG(h.verbose, "[%s] CUDA freeMem %lu mb\n", resp->gpu_id, resp->free / 1024 / 1024); - LOG(h.verbose, "[%s] Compute Capability %d.%d\n", resp->gpu_id, resp->major, resp->minor); - - - - ret = (*h.cuCtxDestroy)(ctx); - if (ret != CUDA_SUCCESS) { - LOG(1, "cuda driver library failed to release device context %d", ret); - } -} - -void nvcuda_get_free(nvcuda_handle_t h, int i, uint64_t *free, uint64_t *total) { - CUresult ret; - CUcontext ctx = NULL; - CUdevice device = -1; - *free = 0; - *total = 0; - - ret = (*h.cuDeviceGet)(&device, i); - if (ret != CUDA_SUCCESS) { - LOG(1, "cuda driver library device failed to initialize"); - return; - } - - - // To get memory we have to set (and release) a context - ret = (*h.cuCtxCreate_v3)(&ctx, NULL, 0, 0, device); - if (ret != CUDA_SUCCESS) { - LOG(1, "cuda driver library failed to get device context %d", ret); - return; - } - - ret = (*h.cuMemGetInfo_v2)(free, total); - if (ret != CUDA_SUCCESS) { - LOG(1, "cuda driver library device memory info lookup failure %d", ret); - // Best effort on failure... - (*h.cuCtxDestroy)(ctx); - return; - } - - ret = (*h.cuCtxDestroy)(ctx); - if (ret != CUDA_SUCCESS) { - LOG(1, "cuda driver library failed to release device context %d", ret); - } -} - -void nvcuda_release(nvcuda_handle_t h) { - LOG(h.verbose, "releasing cuda driver library\n"); - UNLOAD_LIBRARY(h.handle); - // TODO and other context release logic? - h.handle = NULL; -} - -#endif // __APPLE__ \ No newline at end of file diff --git a/ollama/gpu/gpu_info_nvcuda.h b/ollama/gpu/gpu_info_nvcuda.h deleted file mode 100755 index ef2fe8a..0000000 --- a/ollama/gpu/gpu_info_nvcuda.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __APPLE__ -#ifndef __GPU_INFO_NVCUDA_H__ -#define __GPU_INFO_NVCUDA_H__ -#include "gpu_info.h" - -// Just enough typedef's to dlopen/dlsym for memory information -typedef enum cudaError_enum { - CUDA_SUCCESS = 0, - CUDA_ERROR_INVALID_VALUE = 1, - CUDA_ERROR_OUT_OF_MEMORY = 2, - CUDA_ERROR_NOT_INITIALIZED = 3, - CUDA_ERROR_INSUFFICIENT_DRIVER = 35, - CUDA_ERROR_NO_DEVICE = 100, - CUDA_ERROR_SYSTEM_DRIVER_MISMATCH = 803, - CUDA_ERROR_UNKNOWN = 999, - // Other values omitted for now... -} CUresult; - -typedef enum CUdevice_attribute_enum { - CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR = 75, - CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR = 76, - - // TODO - not yet wired up but may be useful for Jetson or other - // integrated GPU scenarios with shared memory - CU_DEVICE_ATTRIBUTE_INTEGRATED = 18 - -} CUdevice_attribute; - -typedef void *nvcudaDevice_t; // Opaque is sufficient -typedef struct nvcudaMemory_st { - uint64_t total; - uint64_t free; -} nvcudaMemory_t; - -typedef struct nvcudaDriverVersion { - int major; - int minor; -} nvcudaDriverVersion_t; - -typedef struct CUuuid_st { - unsigned char bytes[16]; -} CUuuid; - -typedef int CUdevice; -typedef void* CUcontext; - -typedef struct nvcuda_handle { - void *handle; - uint16_t verbose; - int driver_major; - int driver_minor; - CUresult (*cuInit)(unsigned int Flags); - CUresult (*cuDriverGetVersion)(int *driverVersion); - CUresult (*cuDeviceGetCount)(int *); - CUresult (*cuDeviceGet)(CUdevice* device, int ordinal); - CUresult (*cuDeviceGetAttribute)(int* pi, CUdevice_attribute attrib, CUdevice dev); - CUresult (*cuDeviceGetUuid)(CUuuid* uuid, CUdevice dev); // signature compatible with cuDeviceGetUuid_v2 - CUresult (*cuDeviceGetName)(char *name, int len, CUdevice dev); - - // Context specific aspects - CUresult (*cuCtxCreate_v3)(CUcontext* pctx, void *params, int len, unsigned int flags, CUdevice dev); - CUresult (*cuMemGetInfo_v2)(uint64_t* free, uint64_t* total); - CUresult (*cuCtxDestroy)(CUcontext ctx); -} nvcuda_handle_t; - -typedef struct nvcuda_init_resp { - char *err; // If err is non-null handle is invalid - nvcuda_handle_t ch; - int num_devices; - CUresult cudaErr; -} nvcuda_init_resp_t; - -void nvcuda_init(char *nvcuda_lib_path, nvcuda_init_resp_t *resp); -void nvcuda_bootstrap(nvcuda_handle_t ch, int device_id, mem_info_t *resp); -void nvcuda_get_free(nvcuda_handle_t ch, int device_id, uint64_t *free, uint64_t *total); -void nvcuda_release(nvcuda_handle_t ch); - -#endif // __GPU_INFO_NVCUDA_H__ -#endif // __APPLE__ diff --git a/ollama/gpu/gpu_info_nvml.c b/ollama/gpu/gpu_info_nvml.c deleted file mode 100755 index 11293e4..0000000 --- a/ollama/gpu/gpu_info_nvml.c +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __APPLE__ // TODO - maybe consider nvidia support on intel macs? - -#include - -#include "gpu_info_nvml.h" - -void nvml_init(char *nvml_lib_path, nvml_init_resp_t *resp) { - nvmlReturn_t ret; - resp->err = NULL; - const int buflen = 256; - char buf[buflen + 1]; - int i; - - struct lookup { - char *s; - void **p; - } l[] = { - {"nvmlInit_v2", (void *)&resp->ch.nvmlInit_v2}, - {"nvmlShutdown", (void *)&resp->ch.nvmlShutdown}, - {"nvmlDeviceGetHandleByIndex", (void *)&resp->ch.nvmlDeviceGetHandleByIndex}, - {"nvmlDeviceGetMemoryInfo", (void *)&resp->ch.nvmlDeviceGetMemoryInfo}, - {NULL, NULL}, - }; - - resp->ch.handle = LOAD_LIBRARY(nvml_lib_path, RTLD_LAZY); - if (!resp->ch.handle) { - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "library %s load err: %s\n", nvml_lib_path, msg); - snprintf(buf, buflen, - "Unable to load %s library to query for Nvidia GPUs: %s", - nvml_lib_path, msg); - free(msg); - resp->err = strdup(buf); - return; - } - - // TODO once we've squashed the remaining corner cases remove this log - // LOG(resp->ch.verbose, "wiring nvidia management library functions in %s\n", nvml_lib_path); - - for (i = 0; l[i].s != NULL; i++) { - // TODO once we've squashed the remaining corner cases remove this log - // LOG(resp->ch.verbose, "dlsym: %s\n", l[i].s); - - *l[i].p = LOAD_SYMBOL(resp->ch.handle, l[i].s); - if (!*(l[i].p)) { - resp->ch.handle = NULL; - char *msg = LOAD_ERR(); - LOG(resp->ch.verbose, "dlerr: %s\n", msg); - UNLOAD_LIBRARY(resp->ch.handle); - snprintf(buf, buflen, "symbol lookup for %s failed: %s", l[i].s, - msg); - free(msg); - resp->err = strdup(buf); - return; - } - } - - ret = (*resp->ch.nvmlInit_v2)(); - if (ret != NVML_SUCCESS) { - LOG(resp->ch.verbose, "nvmlInit_v2 err: %d\n", ret); - UNLOAD_LIBRARY(resp->ch.handle); - resp->ch.handle = NULL; - snprintf(buf, buflen, "nvml vram init failure: %d", ret); - resp->err = strdup(buf); - return; - } -} - - -void nvml_get_free(nvml_handle_t h, int device_id, uint64_t *free, uint64_t *total, uint64_t *used) { - nvmlDevice_t device; - nvmlMemory_t memInfo = {0}; - nvmlReturn_t ret; - ret = (*h.nvmlDeviceGetHandleByIndex)(device_id, &device); - if (ret != NVML_SUCCESS) { - LOG(1, "unable to get device handle %d: %d", device_id, ret); - *free = 0; - return; - } - - ret = (*h.nvmlDeviceGetMemoryInfo)(device, &memInfo); - if (ret != NVML_SUCCESS) { - LOG(1, "device memory info lookup failure %d: %d", device_id, ret); - *free = 0; - return; - } - *free = memInfo.free; - *total = memInfo.total; - *used = memInfo.used; -} - - -void nvml_release(nvml_handle_t h) { - LOG(h.verbose, "releasing nvml library\n"); - nvmlReturn_t ret; - ret = (*h.nvmlShutdown)(); - if (ret != NVML_SUCCESS) { - LOG(1, "error during nvmlShutdown %d", ret); - } - UNLOAD_LIBRARY(h.handle); - h.handle = NULL; -} - -#endif // __APPLE__ \ No newline at end of file diff --git a/ollama/gpu/gpu_info_nvml.h b/ollama/gpu/gpu_info_nvml.h deleted file mode 100755 index a661f72..0000000 --- a/ollama/gpu/gpu_info_nvml.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __APPLE__ -#ifndef __GPU_INFO_NVML_H__ -#define __GPU_INFO_NVML_H__ -#include "gpu_info.h" - -// Just enough typedef's to dlopen/dlsym for memory information -typedef enum nvmlReturn_enum { - NVML_SUCCESS = 0, - // Other values omitted for now... -} nvmlReturn_t; -typedef void *nvmlDevice_t; // Opaque is sufficient -typedef struct nvmlMemory_st { - unsigned long long total; - unsigned long long free; - unsigned long long used; -} nvmlMemory_t; - -typedef enum nvmlBrandType_enum -{ - NVML_BRAND_UNKNOWN = 0, -} nvmlBrandType_t; - -typedef struct nvml_handle { - void *handle; - uint16_t verbose; - nvmlReturn_t (*nvmlInit_v2)(void); - nvmlReturn_t (*nvmlShutdown)(void); - nvmlReturn_t (*nvmlDeviceGetHandleByIndex)(unsigned int, nvmlDevice_t *); - nvmlReturn_t (*nvmlDeviceGetMemoryInfo)(nvmlDevice_t, nvmlMemory_t *); -} nvml_handle_t; - -typedef struct nvml_init_resp { - char *err; // If err is non-null handle is invalid - nvml_handle_t ch; -} nvml_init_resp_t; - -typedef struct nvml_compute_capability { - char *err; - int major; - int minor; -} nvml_compute_capability_t; - -void nvml_init(char *nvml_lib_path, nvml_init_resp_t *resp); -void nvml_get_free(nvml_handle_t ch, int device_id, uint64_t *free, uint64_t *total, uint64_t *used); -void nvml_release(nvml_handle_t ch); - -#endif // __GPU_INFO_NVML_H__ -#endif // __APPLE__ \ No newline at end of file diff --git a/ollama/gpu/gpu_info_oneapi.c b/ollama/gpu/gpu_info_oneapi.c deleted file mode 100755 index 3ff708e..0000000 --- a/ollama/gpu/gpu_info_oneapi.c +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef __APPLE__ - -#include "gpu_info_oneapi.h" - -#include - -void oneapi_init(char *oneapi_lib_path, oneapi_init_resp_t *resp) { - ze_result_t ret; - resp->err = NULL; - resp->oh.devices = NULL; - resp->oh.num_devices = NULL; - resp->oh.drivers = NULL; - resp->oh.num_drivers = 0; - const int buflen = 256; - char buf[buflen + 1]; - int i, d; - struct lookup { - char *s; - void **p; - } l[] = { - {"zesInit", (void *)&resp->oh.zesInit}, - {"zesDriverGet", (void *)&resp->oh.zesDriverGet}, - {"zesDeviceGet", (void *)&resp->oh.zesDeviceGet}, - {"zesDeviceGetProperties", (void *)&resp->oh.zesDeviceGetProperties}, - {"zesDeviceEnumMemoryModules", - (void *)&resp->oh.zesDeviceEnumMemoryModules}, - {"zesMemoryGetProperties", (void *)&resp->oh.zesMemoryGetProperties}, - {"zesMemoryGetState", (void *)&resp->oh.zesMemoryGetState}, - {NULL, NULL}, - }; - - resp->oh.handle = LOAD_LIBRARY(oneapi_lib_path, RTLD_LAZY); - if (!resp->oh.handle) { - char *msg = LOAD_ERR(); - snprintf(buf, buflen, - "Unable to load %s library to query for Intel GPUs: %s\n", - oneapi_lib_path, msg); - free(msg); - resp->err = strdup(buf); - return; - } - - // TODO once we've squashed the remaining corner cases remove this log - LOG(resp->oh.verbose, - "wiring Level-Zero management library functions in %s\n", - oneapi_lib_path); - - for (i = 0; l[i].s != NULL; i++) { - // TODO once we've squashed the remaining corner cases remove this log - LOG(resp->oh.verbose, "dlsym: %s\n", l[i].s); - - *l[i].p = LOAD_SYMBOL(resp->oh.handle, l[i].s); - if (!*(l[i].p)) { - resp->oh.handle = NULL; - char *msg = LOAD_ERR(); - LOG(resp->oh.verbose, "dlerr: %s\n", msg); - UNLOAD_LIBRARY(resp->oh.handle); - snprintf(buf, buflen, "symbol lookup for %s failed: %s", l[i].s, msg); - free(msg); - resp->err = strdup(buf); - return; - } - } - - LOG(resp->oh.verbose, "calling zesInit\n"); - - ret = (*resp->oh.zesInit)(0); - if (ret != ZE_RESULT_SUCCESS) { - LOG(resp->oh.verbose, "zesInit err: %x\n", ret); - snprintf(buf, buflen, "oneapi vram init failure: %x", ret); - resp->err = strdup(buf); - oneapi_release(resp->oh); - return; - } - - LOG(resp->oh.verbose, "calling zesDriverGet\n"); - ret = (*resp->oh.zesDriverGet)(&resp->oh.num_drivers, NULL); - if (ret != ZE_RESULT_SUCCESS) { - LOG(resp->oh.verbose, "zesDriverGet err: %x\n", ret); - snprintf(buf, buflen, "unable to get driver count: %x", ret); - resp->err = strdup(buf); - oneapi_release(resp->oh); - return; - } - LOG(resp->oh.verbose, "oneapi driver count: %d\n", resp->oh.num_drivers); - resp->oh.drivers = malloc(resp->oh.num_drivers * sizeof(zes_driver_handle_t)); - resp->oh.num_devices = malloc(resp->oh.num_drivers * sizeof(uint32_t)); - memset(&resp->oh.num_devices[0], 0, resp->oh.num_drivers * sizeof(uint32_t)); - resp->oh.devices = - malloc(resp->oh.num_drivers * sizeof(zes_device_handle_t *)); - ret = (*resp->oh.zesDriverGet)(&resp->oh.num_drivers, &resp->oh.drivers[0]); - if (ret != ZE_RESULT_SUCCESS) { - LOG(resp->oh.verbose, "zesDriverGet err: %x\n", ret); - snprintf(buf, buflen, "unable to get driver count: %x", ret); - resp->err = strdup(buf); - oneapi_release(resp->oh); - return; - } - - for (d = 0; d < resp->oh.num_drivers; d++) { - LOG(resp->oh.verbose, "calling zesDeviceGet count %d: %p\n", d, resp->oh.drivers[d]); - ret = (*resp->oh.zesDeviceGet)(resp->oh.drivers[d], - &resp->oh.num_devices[d], NULL); - if (ret != ZE_RESULT_SUCCESS) { - LOG(resp->oh.verbose, "zesDeviceGet err: %x\n", ret); - snprintf(buf, buflen, "unable to get device count: %x", ret); - resp->err = strdup(buf); - oneapi_release(resp->oh); - return; - } - resp->oh.devices[d] = - malloc(resp->oh.num_devices[d] * sizeof(zes_device_handle_t)); - ret = (*resp->oh.zesDeviceGet)( - resp->oh.drivers[d], &resp->oh.num_devices[d], resp->oh.devices[d]); - if (ret != ZE_RESULT_SUCCESS) { - LOG(resp->oh.verbose, "zesDeviceGet err: %x\n", ret); - snprintf(buf, buflen, "unable to get device count: %x", ret); - resp->err = strdup(buf); - oneapi_release(resp->oh); - return; - } - } - - return; -} - -void oneapi_check_vram(oneapi_handle_t h, int driver, int device, - mem_info_t *resp) { - ze_result_t ret; - resp->err = NULL; - uint64_t totalMem = 0; - uint64_t usedMem = 0; - const int buflen = 256; - char buf[buflen + 1]; - int i, d, m; - - if (h.handle == NULL) { - resp->err = strdup("Level-Zero handle not initialized"); - return; - } - - if (driver > h.num_drivers || device > h.num_devices[driver]) { - resp->err = strdup("driver of device index out of bounds"); - return; - } - - resp->total = 0; - resp->free = 0; - - zes_device_ext_properties_t ext_props; - ext_props.stype = ZES_STRUCTURE_TYPE_DEVICE_EXT_PROPERTIES; - ext_props.pNext = NULL; - - zes_device_properties_t props; - props.stype = ZES_STRUCTURE_TYPE_DEVICE_PROPERTIES; - props.pNext = &ext_props; - - ret = (*h.zesDeviceGetProperties)(h.devices[driver][device], &props); - if (ret != ZE_RESULT_SUCCESS) { - snprintf(buf, buflen, "unable to get device properties: %d", ret); - resp->err = strdup(buf); - return; - } - - snprintf(&resp->gpu_name[0], GPU_NAME_LEN, "%s", props.modelName); - - // TODO this needs to map to ONEAPI_DEVICE_SELECTOR syntax - // (this is probably wrong...) - // TODO - the driver isn't included - what if there are multiple drivers? - snprintf(&resp->gpu_id[0], GPU_ID_LEN, "%d", device); - - if (h.verbose) { - // When in verbose mode, report more information about - // the card we discover. - LOG(h.verbose, "[%d:%d] oneAPI device name: %s\n", driver, device, - props.modelName); - LOG(h.verbose, "[%d:%d] oneAPI brand: %s\n", driver, device, - props.brandName); - LOG(h.verbose, "[%d:%d] oneAPI vendor: %s\n", driver, device, - props.vendorName); - LOG(h.verbose, "[%d:%d] oneAPI S/N: %s\n", driver, device, - props.serialNumber); - LOG(h.verbose, "[%d:%d] oneAPI board number: %s\n", driver, device, - props.boardNumber); - } - - // TODO - // Compute Capability equivalent in resp->major, resp->minor, resp->patch - - uint32_t memCount = 0; - ret = (*h.zesDeviceEnumMemoryModules)(h.devices[driver][device], &memCount, - NULL); - if (ret != ZE_RESULT_SUCCESS) { - snprintf(buf, buflen, "unable to enumerate Level-Zero memory modules: %x", - ret); - resp->err = strdup(buf); - return; - } - - LOG(h.verbose, "discovered %d Level-Zero memory modules\n", memCount); - - zes_mem_handle_t *mems = malloc(memCount * sizeof(zes_mem_handle_t)); - (*h.zesDeviceEnumMemoryModules)(h.devices[driver][device], &memCount, mems); - - for (m = 0; m < memCount; m++) { - zes_mem_state_t state; - state.stype = ZES_STRUCTURE_TYPE_MEM_STATE; - state.pNext = NULL; - ret = (*h.zesMemoryGetState)(mems[m], &state); - if (ret != ZE_RESULT_SUCCESS) { - snprintf(buf, buflen, "unable to get memory state: %x", ret); - resp->err = strdup(buf); - free(mems); - return; - } - - resp->total += state.size; - resp->free += state.free; - } - - free(mems); -} - -void oneapi_release(oneapi_handle_t h) { - int d; - LOG(h.verbose, "releasing oneapi library\n"); - for (d = 0; d < h.num_drivers; d++) { - if (h.devices != NULL && h.devices[d] != NULL) { - free(h.devices[d]); - } - } - if (h.devices != NULL) { - free(h.devices); - h.devices = NULL; - } - if (h.num_devices != NULL) { - free(h.num_devices); - h.num_devices = NULL; - } - if (h.drivers != NULL) { - free(h.drivers); - h.drivers = NULL; - } - h.num_drivers = 0; - UNLOAD_LIBRARY(h.handle); - h.handle = NULL; -} - -int oneapi_get_device_count(oneapi_handle_t h, int driver) { - if (h.handle == NULL || h.num_devices == NULL) { - return 0; - } - if (driver > h.num_drivers) { - return 0; - } - return (int)h.num_devices[driver]; -} - -#endif // __APPLE__ diff --git a/ollama/gpu/gpu_info_oneapi.h b/ollama/gpu/gpu_info_oneapi.h deleted file mode 100755 index 97fcecd..0000000 --- a/ollama/gpu/gpu_info_oneapi.h +++ /dev/null @@ -1,203 +0,0 @@ -#ifndef __APPLE__ -#ifndef __GPU_INFO_ONEAPI_H__ -#define __GPU_INFO_ONEAPI_H__ -#include "gpu_info.h" - -#define ZE_MAX_DEVICE_NAME 256 -#define ZE_MAX_DEVICE_UUID_SIZE 16 -#define ZES_STRING_PROPERTY_SIZE 64 -#define ZE_BIT(_i) (1 << _i) - -// Just enough typedef's to dlopen/dlsym for memory information -typedef enum ze_result_t { - ZE_RESULT_SUCCESS = 0, - // Other values omitted for now... -} ze_result_t; - -typedef uint8_t ze_bool_t; -typedef struct _zes_driver_handle_t *zes_driver_handle_t; -typedef struct _zes_device_handle_t *zes_device_handle_t; -typedef struct _zes_mem_handle_t *zes_mem_handle_t; - -typedef enum _ze_structure_type_t { - ZE_STRUCTURE_TYPE_FORCE_UINT32 = 0x7fffffff -} ze_structure_type_t; - -typedef enum _zes_structure_type_t { - ZES_STRUCTURE_TYPE_DEVICE_PROPERTIES = 0x1, - ZES_STRUCTURE_TYPE_MEM_PROPERTIES = 0xb, - ZES_STRUCTURE_TYPE_MEM_STATE = 0x1e, - ZES_STRUCTURE_TYPE_DEVICE_EXT_PROPERTIES = 0x2d, - ZES_STRUCTURE_TYPE_FORCE_UINT32 = 0x7fffffff -} zes_structure_type_t; - -typedef enum _zes_mem_type_t { - ZES_MEM_TYPE_FORCE_UINT32 = 0x7fffffff -} zes_mem_type_t; - -typedef enum _zes_mem_loc_t { - ZES_MEM_LOC_SYSTEM = 0, - ZES_MEM_LOC_DEVICE = 1, - ZES_MEM_LOC_FORCE_UINT32 = 0x7fffffff -} zes_mem_loc_t; - -typedef enum _zes_mem_health_t { - ZES_MEM_HEALTH_FORCE_UINT32 = 0x7fffffff -} zes_mem_health_t; - -typedef struct _ze_device_uuid_t { - uint8_t id[ZE_MAX_DEVICE_UUID_SIZE]; -} ze_device_uuid_t; - -typedef struct _zes_uuid_t { - uint8_t id[ZE_MAX_DEVICE_UUID_SIZE]; -} zes_uuid_t; - -typedef enum _ze_device_type_t { - ZE_DEVICE_TYPE_GPU = 1, - ZE_DEVICE_TYPE_CPU = 2, - ZE_DEVICE_TYPE_FPGA = 3, - ZE_DEVICE_TYPE_MCA = 4, - ZE_DEVICE_TYPE_VPU = 5, - ZE_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff -} ze_device_type_t; - -typedef enum _zes_device_type_t { - ZES_DEVICE_TYPE_GPU = 1, - ZES_DEVICE_TYPE_CPU = 2, - ZES_DEVICE_TYPE_FPGA = 3, - ZES_DEVICE_TYPE_MCA = 4, - ZES_DEVICE_TYPE_VPU = 5, - ZES_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff -} zes_device_type_t; - -typedef uint32_t ze_device_property_flags_t; -typedef enum _ze_device_property_flag_t { - ZE_DEVICE_PROPERTY_FLAG_INTEGRATED = ZE_BIT(0), - ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE = ZE_BIT(1), - ZE_DEVICE_PROPERTY_FLAG_ECC = ZE_BIT(2), - ZE_DEVICE_PROPERTY_FLAG_ONDEMANDPAGING = ZE_BIT(3), - ZE_DEVICE_PROPERTY_FLAG_FORCE_UINT32 = 0x7fffffff -} ze_device_property_flag_t; - -typedef uint32_t zes_device_property_flags_t; -typedef enum _zes_device_property_flag_t { - ZES_DEVICE_PROPERTY_FLAG_INTEGRATED = ZE_BIT(0), - ZES_DEVICE_PROPERTY_FLAG_SUBDEVICE = ZE_BIT(1), - ZES_DEVICE_PROPERTY_FLAG_ECC = ZE_BIT(2), - ZES_DEVICE_PROPERTY_FLAG_ONDEMANDPAGING = ZE_BIT(3), - ZES_DEVICE_PROPERTY_FLAG_FORCE_UINT32 = 0x7fffffff -} zes_device_property_flag_t; - -typedef struct _ze_device_properties_t { - ze_structure_type_t stype; - void *pNext; - ze_device_type_t type; - uint32_t vendorId; - uint32_t deviceId; - ze_device_property_flags_t flags; - uint32_t subdeviceId; - uint32_t coreClockRate; - uint64_t maxMemAllocSize; - uint32_t maxHardwareContexts; - uint32_t maxCommandQueuePriority; - uint32_t numThreadsPerEU; - uint32_t physicalEUSimdWidth; - uint32_t numEUsPerSubslice; - uint32_t numSubslicesPerSlice; - uint32_t numSlices; - uint64_t timerResolution; - uint32_t timestampValidBits; - uint32_t kernelTimestampValidBits; - ze_device_uuid_t uuid; - char name[ZE_MAX_DEVICE_NAME]; -} ze_device_properties_t; - -typedef struct _zes_device_properties_t { - zes_structure_type_t stype; - void *pNext; - ze_device_properties_t core; - uint32_t numSubdevices; - char serialNumber[ZES_STRING_PROPERTY_SIZE]; - char boardNumber[ZES_STRING_PROPERTY_SIZE]; - char brandName[ZES_STRING_PROPERTY_SIZE]; - char modelName[ZES_STRING_PROPERTY_SIZE]; - char vendorName[ZES_STRING_PROPERTY_SIZE]; - char driverVersion[ZES_STRING_PROPERTY_SIZE]; -} zes_device_properties_t; - -typedef struct _zes_device_ext_properties_t { - zes_structure_type_t stype; - void *pNext; - zes_uuid_t uuid; - zes_device_type_t type; - zes_device_property_flags_t flags; -} zes_device_ext_properties_t; - -typedef struct _zes_mem_properties_t { - zes_structure_type_t stype; - void *pNext; - zes_mem_type_t type; - ze_bool_t onSubdevice; - uint32_t subdeviceId; - zes_mem_loc_t location; - uint64_t physicalSize; - int32_t busWidth; - int32_t numChannels; -} zes_mem_properties_t; - -typedef struct _zes_mem_state_t { - zes_structure_type_t stype; - const void *pNext; - zes_mem_health_t health; - uint64_t free; - uint64_t size; -} zes_mem_state_t; - -typedef struct oneapi_handle { - void *handle; - uint16_t verbose; - - uint32_t num_drivers; - zes_driver_handle_t *drivers; - uint32_t *num_devices; - zes_device_handle_t **devices; - - // TODO Driver major, minor information - // int driver_major; - // int driver_minor; - - ze_result_t (*zesInit)(int); - ze_result_t (*zesDriverGet)(uint32_t *pCount, zes_driver_handle_t *phDrivers); - ze_result_t (*zesDeviceGet)(zes_driver_handle_t hDriver, uint32_t *pCount, - zes_device_handle_t *phDevices); - ze_result_t (*zesDeviceGetProperties)(zes_device_handle_t hDevice, - zes_device_properties_t *pProperties); - ze_result_t (*zesDeviceEnumMemoryModules)(zes_device_handle_t hDevice, - uint32_t *pCount, - zes_mem_handle_t *phMemory); - ze_result_t (*zesMemoryGetProperties)(zes_mem_handle_t hMemory, - zes_mem_properties_t *pProperties); - ze_result_t (*zesMemoryGetState)(zes_mem_handle_t hMemory, - zes_mem_state_t *pState); - -} oneapi_handle_t; - -typedef struct oneapi_init_resp { - char *err; // If err is non-null handle is invalid - oneapi_handle_t oh; -} oneapi_init_resp_t; - -typedef struct oneapi_version_resp { - ze_result_t status; - char *str; // Contains version or error string if status != 0 -} oneapi_version_resp_t; - -void oneapi_init(char *oneapi_lib_path, oneapi_init_resp_t *resp); -void oneapi_check_vram(oneapi_handle_t h, int driver, int device, - mem_info_t *resp); -void oneapi_release(oneapi_handle_t h); -int oneapi_get_device_count(oneapi_handle_t h, int driver); - -#endif // __GPU_INFO_INTEL_H__ -#endif // __APPLE__ diff --git a/ollama/gpu/gpu_linux.go b/ollama/gpu/gpu_linux.go deleted file mode 100755 index d6d2675..0000000 --- a/ollama/gpu/gpu_linux.go +++ /dev/null @@ -1,92 +0,0 @@ -package gpu - -import ( - "bufio" - "fmt" - "os" - "strings" - - "github.com/ollama/ollama/format" -) - -var CudartGlobs = []string{ - "/usr/local/cuda/lib64/libcudart.so*", - "/usr/lib/x86_64-linux-gnu/nvidia/current/libcudart.so*", - "/usr/lib/x86_64-linux-gnu/libcudart.so*", - "/usr/lib/wsl/lib/libcudart.so*", - "/usr/lib/wsl/drivers/*/libcudart.so*", - "/opt/cuda/lib64/libcudart.so*", - "/usr/local/cuda*/targets/aarch64-linux/lib/libcudart.so*", - "/usr/lib/aarch64-linux-gnu/nvidia/current/libcudart.so*", - "/usr/lib/aarch64-linux-gnu/libcudart.so*", - "/usr/local/cuda/lib*/libcudart.so*", - "/usr/lib*/libcudart.so*", - "/usr/local/lib*/libcudart.so*", -} - -var NvmlGlobs = []string{} - -var NvcudaGlobs = []string{ - "/usr/local/cuda*/targets/*/lib/libcuda.so*", - "/usr/lib/*-linux-gnu/nvidia/current/libcuda.so*", - "/usr/lib/*-linux-gnu/libcuda.so*", - "/usr/lib/wsl/lib/libcuda.so*", - "/usr/lib/wsl/drivers/*/libcuda.so*", - "/opt/cuda/lib*/libcuda.so*", - "/usr/local/cuda/lib*/libcuda.so*", - "/usr/lib*/libcuda.so*", - "/usr/local/lib*/libcuda.so*", -} - -var OneapiGlobs = []string{ - "/usr/lib/x86_64-linux-gnu/libze_intel_gpu.so*", - "/usr/lib*/libze_intel_gpu.so*", -} - -var ( - CudartMgmtName = "libcudart.so*" - NvcudaMgmtName = "libcuda.so*" - NvmlMgmtName = "" // not currently wired on linux - OneapiMgmtName = "libze_intel_gpu.so" -) - -func GetCPUMem() (memInfo, error) { - var mem memInfo - var total, available, free, buffers, cached, freeSwap uint64 - f, err := os.Open("/proc/meminfo") - if err != nil { - return mem, err - } - defer f.Close() - s := bufio.NewScanner(f) - for s.Scan() { - line := s.Text() - switch { - case strings.HasPrefix(line, "MemTotal:"): - _, err = fmt.Sscanf(line, "MemTotal:%d", &total) - case strings.HasPrefix(line, "MemAvailable:"): - _, err = fmt.Sscanf(line, "MemAvailable:%d", &available) - case strings.HasPrefix(line, "MemFree:"): - _, err = fmt.Sscanf(line, "MemFree:%d", &free) - case strings.HasPrefix(line, "Buffers:"): - _, err = fmt.Sscanf(line, "Buffers:%d", &buffers) - case strings.HasPrefix(line, "Cached:"): - _, err = fmt.Sscanf(line, "Cached:%d", &cached) - case strings.HasPrefix(line, "SwapFree:"): - _, err = fmt.Sscanf(line, "SwapFree:%d", &freeSwap) - default: - continue - } - if err != nil { - return mem, err - } - } - mem.TotalMemory = total * format.KibiByte - mem.FreeSwap = freeSwap * format.KibiByte - if available > 0 { - mem.FreeMemory = available * format.KibiByte - } else { - mem.FreeMemory = (free + buffers + cached) * format.KibiByte - } - return mem, nil -} diff --git a/ollama/gpu/gpu_oneapi.go b/ollama/gpu/gpu_oneapi.go deleted file mode 100755 index 9864bde..0000000 --- a/ollama/gpu/gpu_oneapi.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build linux || windows - -package gpu - -import ( - "log/slog" - "strings" -) - -func oneapiGetVisibleDevicesEnv(gpuInfo []GpuInfo) (string, string) { - ids := []string{} - for _, info := range gpuInfo { - if info.Library != "oneapi" { - // TODO shouldn't happen if things are wired correctly... - slog.Debug("oneapiGetVisibleDevicesEnv skipping over non-sycl device", "library", info.Library) - continue - } - ids = append(ids, info.ID) - } - return "ONEAPI_DEVICE_SELECTOR", "level_zero:" + strings.Join(ids, ",") -} diff --git a/ollama/gpu/gpu_test.go b/ollama/gpu/gpu_test.go deleted file mode 100755 index 46d3201..0000000 --- a/ollama/gpu/gpu_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package gpu - -import ( - "runtime" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestBasicGetGPUInfo(t *testing.T) { - info := GetGPUInfo() - assert.NotEmpty(t, len(info)) - assert.Contains(t, "cuda rocm cpu metal", info[0].Library) - if info[0].Library != "cpu" { - assert.Greater(t, info[0].TotalMemory, uint64(0)) - assert.Greater(t, info[0].FreeMemory, uint64(0)) - } -} - -func TestCPUMemInfo(t *testing.T) { - info, err := GetCPUMem() - require.NoError(t, err) - switch runtime.GOOS { - case "darwin": - t.Skip("CPU memory not populated on darwin") - case "linux", "windows": - assert.Greater(t, info.TotalMemory, uint64(0)) - assert.Greater(t, info.FreeMemory, uint64(0)) - default: - return - } -} - -// TODO - add some logic to figure out card type through other means and actually verify we got back what we expected diff --git a/ollama/gpu/gpu_windows.go b/ollama/gpu/gpu_windows.go deleted file mode 100755 index 2ec72ba..0000000 --- a/ollama/gpu/gpu_windows.go +++ /dev/null @@ -1,57 +0,0 @@ -package gpu - -import ( - "fmt" - "syscall" - "unsafe" -) - -type MEMORYSTATUSEX struct { - length uint32 - MemoryLoad uint32 - TotalPhys uint64 - AvailPhys uint64 - TotalPageFile uint64 - AvailPageFile uint64 - TotalVirtual uint64 - AvailVirtual uint64 - AvailExtendedVirtual uint64 -} - -var ( - k32 = syscall.NewLazyDLL("kernel32.dll") - globalMemoryStatusExProc = k32.NewProc("GlobalMemoryStatusEx") - sizeofMemoryStatusEx = uint32(unsafe.Sizeof(MEMORYSTATUSEX{})) -) - -var CudartGlobs = []string{ - "c:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v*\\bin\\cudart64_*.dll", -} - -var NvmlGlobs = []string{ - "c:\\Windows\\System32\\nvml.dll", -} - -var NvcudaGlobs = []string{ - "c:\\windows\\system*\\nvcuda.dll", -} - -var OneapiGlobs = []string{ - "c:\\Windows\\System32\\DriverStore\\FileRepository\\*\\ze_intel_gpu64.dll", -} - -var ( - CudartMgmtName = "cudart64_*.dll" - NvcudaMgmtName = "nvcuda.dll" - NvmlMgmtName = "nvml.dll" - OneapiMgmtName = "ze_intel_gpu64.dll" -) - -func GetCPUMem() (memInfo, error) { - memStatus := MEMORYSTATUSEX{length: sizeofMemoryStatusEx} - r1, _, err := globalMemoryStatusExProc.Call(uintptr(unsafe.Pointer(&memStatus))) - if r1 == 0 { - return memInfo{}, fmt.Errorf("GlobalMemoryStatusEx failed: %w", err) - } - return memInfo{TotalMemory: memStatus.TotalPhys, FreeMemory: memStatus.AvailPhys, FreeSwap: memStatus.AvailPageFile}, nil -} diff --git a/ollama/gpu/types.go b/ollama/gpu/types.go deleted file mode 100755 index 8d22b06..0000000 --- a/ollama/gpu/types.go +++ /dev/null @@ -1,145 +0,0 @@ -package gpu - -import ( - "fmt" - "log/slog" - - "github.com/ollama/ollama/format" -) - -type memInfo struct { - TotalMemory uint64 `json:"total_memory,omitempty"` - FreeMemory uint64 `json:"free_memory,omitempty"` - FreeSwap uint64 `json:"free_swap,omitempty"` -} - -// Beginning of an `ollama info` command -type GpuInfo struct { - memInfo - Library string `json:"library,omitempty"` - - // Optional variant to select (e.g. versions, cpu feature flags) - Variant CPUCapability `json:"variant"` - - // MinimumMemory represents the minimum memory required to use the GPU - MinimumMemory uint64 `json:"-"` - - // Any extra PATH/LD_LIBRARY_PATH dependencies required for the Library to operate properly - DependencyPath string `json:"lib_path,omitempty"` - - // Extra environment variables specific to the GPU as list of [key,value] - EnvWorkarounds [][2]string `json:"envs,omitempty"` - - // Set to true if we can NOT reliably discover FreeMemory. A value of true indicates - // the FreeMemory is best effort, and may over or under report actual memory usage - // False indicates FreeMemory can generally be trusted on this GPU - UnreliableFreeMemory bool - - // GPU information - ID string `json:"gpu_id"` // string to use for selection of this specific GPU - Name string `json:"name"` // user friendly name if available - Compute string `json:"compute"` // Compute Capability or gfx - - // Driver Information - TODO no need to put this on each GPU - DriverMajor int `json:"driver_major,omitempty"` - DriverMinor int `json:"driver_minor,omitempty"` - - // TODO other performance capability info to help in scheduling decisions -} - -type CPUInfo struct { - GpuInfo -} - -type CudaGPUInfo struct { - GpuInfo - OSOverhead uint64 // Memory overhead between the driver library and management library - index int //nolint:unused,nolintlint -} -type CudaGPUInfoList []CudaGPUInfo - -type RocmGPUInfo struct { - GpuInfo - usedFilepath string //nolint:unused,nolintlint - index int //nolint:unused,nolintlint -} -type RocmGPUInfoList []RocmGPUInfo - -type OneapiGPUInfo struct { - GpuInfo - driverIndex int //nolint:unused,nolintlint - gpuIndex int //nolint:unused,nolintlint -} -type OneapiGPUInfoList []OneapiGPUInfo - -type GpuInfoList []GpuInfo - -// Split up the set of gpu info's by Library and variant -func (l GpuInfoList) ByLibrary() []GpuInfoList { - resp := []GpuInfoList{} - libs := []string{} - for _, info := range l { - found := false - requested := info.Library - if info.Variant != CPUCapabilityNone { - requested += "_" + info.Variant.String() - } - for i, lib := range libs { - if lib == requested { - resp[i] = append(resp[i], info) - found = true - break - } - } - if !found { - libs = append(libs, info.Library) - resp = append(resp, []GpuInfo{info}) - } - } - return resp -} - -// Report the GPU information into the log an Info level -func (l GpuInfoList) LogDetails() { - for _, g := range l { - slog.Info("inference compute", - "id", g.ID, - "library", g.Library, - "compute", g.Compute, - "driver", fmt.Sprintf("%d.%d", g.DriverMajor, g.DriverMinor), - "name", g.Name, - "total", format.HumanBytes2(g.TotalMemory), - "available", format.HumanBytes2(g.FreeMemory), - ) - } -} - -// Sort by Free Space -type ByFreeMemory []GpuInfo - -func (a ByFreeMemory) Len() int { return len(a) } -func (a ByFreeMemory) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a ByFreeMemory) Less(i, j int) bool { return a[i].FreeMemory < a[j].FreeMemory } - -type CPUCapability uint32 - -// Override at build time when building base GPU runners -var GPURunnerCPUCapability = CPUCapabilityAVX - -const ( - CPUCapabilityNone CPUCapability = iota - CPUCapabilityAVX - CPUCapabilityAVX2 - // TODO AVX512 -) - -func (c CPUCapability) String() string { - switch c { - case CPUCapabilityAVX: - return "avx" - case CPUCapabilityAVX2: - return "avx2" - default: - return "no vector extensions" - } -} diff --git a/ollama/integration/README.md b/ollama/integration/README.md deleted file mode 100755 index e2bdd6b..0000000 --- a/ollama/integration/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Integration Tests - -This directory contains integration tests to exercise Ollama end-to-end to verify behavior - -By default, these tests are disabled so `go test ./...` will exercise only unit tests. To run integration tests you must pass the integration tag. `go test -tags=integration ./...` - - -The integration tests have 2 modes of operating. - -1. By default, they will start the server on a random port, run the tests, and then shutdown the server. -2. If `OLLAMA_TEST_EXISTING` is set to a non-empty string, the tests will run against an existing running server, which can be remote diff --git a/ollama/integration/basic_test.go b/ollama/integration/basic_test.go deleted file mode 100755 index 8e35b5c..0000000 --- a/ollama/integration/basic_test.go +++ /dev/null @@ -1,63 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "log/slog" - "os" - "runtime" - "testing" - "time" - - "github.com/ollama/ollama/api" - "github.com/stretchr/testify/require" -) - -func TestOrcaMiniBlueSky(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - // Set up the test data - req := api.GenerateRequest{ - Model: "orca-mini", - Prompt: "why is the sky blue?", - Stream: &stream, - Options: map[string]interface{}{ - "temperature": 0, - "seed": 123, - }, - } - GenerateTestHelper(ctx, t, req, []string{"rayleigh", "scattering"}) -} - -func TestUnicodeModelDir(t *testing.T) { - // This is only useful for Windows with utf-16 characters, so skip this test for other platforms - if runtime.GOOS != "windows" { - t.Skip("Unicode test only applicable to windows") - } - // Only works for local testing - if os.Getenv("OLLAMA_TEST_EXISTING") != "" { - t.Skip("TestUnicodeModelDir only works for local testing, skipping") - } - - modelDir, err := os.MkdirTemp("", "ollama_埃") - require.NoError(t, err) - defer os.RemoveAll(modelDir) - slog.Info("unicode", "OLLAMA_MODELS", modelDir) - - t.Setenv("OLLAMA_MODELS", modelDir) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - req := api.GenerateRequest{ - Model: "orca-mini", - Prompt: "why is the sky blue?", - Stream: &stream, - Options: map[string]interface{}{ - "temperature": 0, - "seed": 123, - }, - } - GenerateTestHelper(ctx, t, req, []string{"rayleigh", "scattering"}) -} diff --git a/ollama/integration/concurrency_test.go b/ollama/integration/concurrency_test.go deleted file mode 100755 index 42e9d07..0000000 --- a/ollama/integration/concurrency_test.go +++ /dev/null @@ -1,270 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "log/slog" - "os" - "strconv" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/ollama/ollama/api" - "github.com/ollama/ollama/format" -) - -func TestMultiModelConcurrency(t *testing.T) { - var ( - req = [2]api.GenerateRequest{ - { - Model: "orca-mini", - Prompt: "why is the ocean blue?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "tinydolphin", - Prompt: "what is the origin of the us thanksgiving holiday?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, - } - resp = [2][]string{ - {"sunlight"}, - {"england", "english", "massachusetts", "pilgrims", "british"}, - } - ) - var wg sync.WaitGroup - wg.Add(len(req)) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*240) - defer cancel() - - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - - for i := 0; i < len(req); i++ { - require.NoError(t, PullIfMissing(ctx, client, req[i].Model)) - } - - for i := 0; i < len(req); i++ { - go func(i int) { - defer wg.Done() - DoGenerate(ctx, t, client, req[i], resp[i], 60*time.Second, 10*time.Second) - }(i) - } - wg.Wait() -} - -func TestIntegrationConcurrentPredictOrcaMini(t *testing.T) { - req, resp := GenerateRequests() - reqLimit := len(req) - iterLimit := 5 - - if s := os.Getenv("OLLAMA_MAX_VRAM"); s != "" { - maxVram, err := strconv.ParseUint(s, 10, 64) - require.NoError(t, err) - // Don't hammer on small VRAM cards... - if maxVram < 4*format.GibiByte { - reqLimit = min(reqLimit, 2) - iterLimit = 2 - } - } - - ctx, cancel := context.WithTimeout(context.Background(), 9*time.Minute) - defer cancel() - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - - // Get the server running (if applicable) warm the model up with a single initial request - DoGenerate(ctx, t, client, req[0], resp[0], 60*time.Second, 10*time.Second) - - var wg sync.WaitGroup - wg.Add(reqLimit) - for i := 0; i < reqLimit; i++ { - go func(i int) { - defer wg.Done() - for j := 0; j < iterLimit; j++ { - slog.Info("Starting", "req", i, "iter", j) - // On slower GPUs it can take a while to process the concurrent requests - // so we allow a much longer initial timeout - DoGenerate(ctx, t, client, req[i], resp[i], 120*time.Second, 20*time.Second) - } - }(i) - } - wg.Wait() -} - -// Stress the system if we know how much VRAM it has, and attempt to load more models than will fit -func TestMultiModelStress(t *testing.T) { - s := os.Getenv("OLLAMA_MAX_VRAM") // TODO - discover actual VRAM - if s == "" { - t.Skip("OLLAMA_MAX_VRAM not specified, can't pick the right models for the stress test") - } - - maxVram, err := strconv.ParseUint(s, 10, 64) - if err != nil { - t.Fatal(err) - } - - type model struct { - name string - size uint64 // Approximate amount of VRAM they typically use when fully loaded in VRAM - } - - smallModels := []model{ - { - name: "orca-mini", - size: 2992 * format.MebiByte, - }, - { - name: "phi", - size: 2616 * format.MebiByte, - }, - { - name: "gemma:2b", - size: 2364 * format.MebiByte, - }, - { - name: "stable-code:3b", - size: 2608 * format.MebiByte, - }, - { - name: "starcoder2:3b", - size: 2166 * format.MebiByte, - }, - } - mediumModels := []model{ - { - name: "llama2", - size: 5118 * format.MebiByte, - }, - { - name: "mistral", - size: 4620 * format.MebiByte, - }, - { - name: "orca-mini:7b", - size: 5118 * format.MebiByte, - }, - { - name: "dolphin-mistral", - size: 4620 * format.MebiByte, - }, - { - name: "gemma:7b", - size: 5000 * format.MebiByte, - }, - { - name: "codellama:7b", - size: 5118 * format.MebiByte, - }, - } - - // These seem to be too slow to be useful... - // largeModels := []model{ - // { - // name: "llama2:13b", - // size: 7400 * format.MebiByte, - // }, - // { - // name: "codellama:13b", - // size: 7400 * format.MebiByte, - // }, - // { - // name: "orca-mini:13b", - // size: 7400 * format.MebiByte, - // }, - // { - // name: "gemma:7b", - // size: 5000 * format.MebiByte, - // }, - // { - // name: "starcoder2:15b", - // size: 9100 * format.MebiByte, - // }, - // } - - var chosenModels []model - switch { - case maxVram < 10000*format.MebiByte: - slog.Info("selecting small models") - chosenModels = smallModels - // case maxVram < 30000*format.MebiByte: - default: - slog.Info("selecting medium models") - chosenModels = mediumModels - // default: - // slog.Info("selecting large models") - // chosenModels = largModels - } - - req, resp := GenerateRequests() - - for i := range req { - if i > len(chosenModels) { - break - } - req[i].Model = chosenModels[i].name - } - - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) // TODO baseline -- 10m too short - defer cancel() - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - - // Make sure all the models are pulled before we get started - for _, r := range req { - require.NoError(t, PullIfMissing(ctx, client, r.Model)) - } - - var wg sync.WaitGroup - consumed := uint64(256 * format.MebiByte) // Assume some baseline usage - for i := 0; i < len(req); i++ { - // Always get at least 2 models, but dont' overshoot VRAM too much or we'll take too long - if i > 1 && consumed > maxVram { - slog.Info("achieved target vram exhaustion", "count", i, "vram", format.HumanBytes2(maxVram), "models", format.HumanBytes2(consumed)) - break - } - consumed += chosenModels[i].size - slog.Info("target vram", "count", i, "vram", format.HumanBytes2(maxVram), "models", format.HumanBytes2(consumed)) - - wg.Add(1) - go func(i int) { - defer wg.Done() - for j := 0; j < 3; j++ { - slog.Info("Starting", "req", i, "iter", j, "model", req[i].Model) - DoGenerate(ctx, t, client, req[i], resp[i], 120*time.Second, 5*time.Second) - } - }(i) - } - go func() { - for { - time.Sleep(2 * time.Second) - select { - case <-ctx.Done(): - return - default: - models, err := client.ListRunning(ctx) - if err != nil { - slog.Warn("failed to list running models", "error", err) - continue - } - for _, m := range models.Models { - slog.Info("loaded model snapshot", "model", m) - } - } - } - }() - wg.Wait() -} diff --git a/ollama/integration/context_test.go b/ollama/integration/context_test.go deleted file mode 100755 index f1342e1..0000000 --- a/ollama/integration/context_test.go +++ /dev/null @@ -1,34 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "testing" - "time" - - "github.com/ollama/ollama/api" -) - -func TestContextExhaustion(t *testing.T) { - // Longer needed for small footprint GPUs - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() - // Set up the test data - req := api.GenerateRequest{ - Model: "llama2", - Prompt: "Write me a story with a ton of emojis?", - Stream: &stream, - Options: map[string]interface{}{ - "temperature": 0, - "seed": 123, - "num_ctx": 128, - }, - } - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - if err := PullIfMissing(ctx, client, req.Model); err != nil { - t.Fatalf("PullIfMissing failed: %v", err) - } - DoGenerate(ctx, t, client, req, []string{"once", "upon", "lived"}, 120*time.Second, 10*time.Second) -} diff --git a/ollama/integration/embed_test.go b/ollama/integration/embed_test.go deleted file mode 100755 index 10333d5..0000000 --- a/ollama/integration/embed_test.go +++ /dev/null @@ -1,209 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "math" - "testing" - "time" - - "github.com/ollama/ollama/api" -) - -func floatsEqual32(a, b float32) bool { - return math.Abs(float64(a-b)) <= 1e-4 -} - -func floatsEqual64(a, b float64) bool { - return math.Abs(a-b) <= 1e-4 -} - -func TestAllMiniLMEmbeddings(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - req := api.EmbeddingRequest{ - Model: "all-minilm", - Prompt: "why is the sky blue?", - } - - res, err := embeddingTestHelper(ctx, t, req) - - if err != nil { - t.Fatalf("error: %v", err) - } - - if len(res.Embedding) != 384 { - t.Fatalf("expected 384 floats, got %d", len(res.Embedding)) - } - - if !floatsEqual64(res.Embedding[0], 0.06642947345972061) { - t.Fatalf("expected 0.06642947345972061, got %.16f", res.Embedding[0]) - } -} - -func TestAllMiniLMEmbed(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - req := api.EmbedRequest{ - Model: "all-minilm", - Input: "why is the sky blue?", - } - - res, err := embedTestHelper(ctx, t, req) - - if err != nil { - t.Fatalf("error: %v", err) - } - - if len(res.Embeddings) != 1 { - t.Fatalf("expected 1 embedding, got %d", len(res.Embeddings)) - } - - if len(res.Embeddings[0]) != 384 { - t.Fatalf("expected 384 floats, got %d", len(res.Embeddings[0])) - } - - if !floatsEqual32(res.Embeddings[0][0], 0.010071031) { - t.Fatalf("expected 0.010071031, got %.8f", res.Embeddings[0][0]) - } - - if res.PromptEvalCount != 8 { - t.Fatalf("expected 8 prompt tokens, got %d", res.PromptEvalCount) - } -} - -func TestAllMiniLMBatchEmbed(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - req := api.EmbedRequest{ - Model: "all-minilm", - Input: []string{"why is the sky blue?", "why is the grass green?"}, - } - - res, err := embedTestHelper(ctx, t, req) - - if err != nil { - t.Fatalf("error: %v", err) - } - - if len(res.Embeddings) != 2 { - t.Fatalf("expected 2 embeddings, got %d", len(res.Embeddings)) - } - - if len(res.Embeddings[0]) != 384 { - t.Fatalf("expected 384 floats, got %d", len(res.Embeddings[0])) - } - - if !floatsEqual32(res.Embeddings[0][0], 0.010071031) || !floatsEqual32(res.Embeddings[1][0], -0.009802706) { - t.Fatalf("expected 0.010071031 and -0.009802706, got %.8f and %.8f", res.Embeddings[0][0], res.Embeddings[1][0]) - } - - if res.PromptEvalCount != 16 { - t.Fatalf("expected 16 prompt tokens, got %d", res.PromptEvalCount) - } -} - -func TestAllMiniLMEmbedTruncate(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - truncTrue, truncFalse := true, false - - type testReq struct { - Name string - Request api.EmbedRequest - } - - reqs := []testReq{ - { - Name: "Target Truncation", - Request: api.EmbedRequest{ - Model: "all-minilm", - Input: "why", - }, - }, - { - Name: "Default Truncate", - Request: api.EmbedRequest{ - Model: "all-minilm", - Input: "why is the sky blue?", - Options: map[string]any{"num_ctx": 1}, - }, - }, - { - Name: "Explicit Truncate", - Request: api.EmbedRequest{ - Model: "all-minilm", - Input: "why is the sky blue?", - Truncate: &truncTrue, - Options: map[string]any{"num_ctx": 1}, - }, - }, - } - - res := make(map[string]*api.EmbedResponse) - - for _, req := range reqs { - response, err := embedTestHelper(ctx, t, req.Request) - if err != nil { - t.Fatalf("error: %v", err) - } - res[req.Name] = response - } - - if res["Target Truncation"].Embeddings[0][0] != res["Default Truncate"].Embeddings[0][0] { - t.Fatal("expected default request to truncate correctly") - } - - if res["Default Truncate"].Embeddings[0][0] != res["Explicit Truncate"].Embeddings[0][0] { - t.Fatal("expected default request and truncate true request to be the same") - } - - // check that truncate set to false returns an error if context length is exceeded - _, err := embedTestHelper(ctx, t, api.EmbedRequest{ - Model: "all-minilm", - Input: "why is the sky blue?", - Truncate: &truncFalse, - Options: map[string]any{"num_ctx": 1}, - }) - - if err == nil { - t.Fatal("expected error, got nil") - } -} - -func embeddingTestHelper(ctx context.Context, t *testing.T, req api.EmbeddingRequest) (*api.EmbeddingResponse, error) { - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - if err := PullIfMissing(ctx, client, req.Model); err != nil { - t.Fatalf("failed to pull model %s: %v", req.Model, err) - } - - response, err := client.Embeddings(ctx, &req) - - if err != nil { - return nil, err - } - - return response, nil -} - -func embedTestHelper(ctx context.Context, t *testing.T, req api.EmbedRequest) (*api.EmbedResponse, error) { - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - if err := PullIfMissing(ctx, client, req.Model); err != nil { - t.Fatalf("failed to pull model %s: %v", req.Model, err) - } - - response, err := client.Embed(ctx, &req) - - if err != nil { - return nil, err - } - - return response, nil -} diff --git a/ollama/integration/llm_image_test.go b/ollama/integration/llm_image_test.go deleted file mode 100755 index d0c861c..0000000 --- a/ollama/integration/llm_image_test.go +++ /dev/null @@ -1,537 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "encoding/base64" - "testing" - "time" - - "github.com/ollama/ollama/api" - "github.com/stretchr/testify/require" -) - -func TestIntegrationMultimodal(t *testing.T) { - image, err := base64.StdEncoding.DecodeString(imageEncoding) - require.NoError(t, err) - req := api.GenerateRequest{ - Model: "llava:7b", - Prompt: "what does the text in this image say?", - Stream: &stream, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - Images: []api.ImageData{ - image, - }, - } - - // Note: sometimes it returns "the ollamas" sometimes "the ollams" - resp := "the ollam" - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) - defer cancel() - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - require.NoError(t, PullIfMissing(ctx, client, req.Model)) - // llava models on CPU can be quite slow to start, - DoGenerate(ctx, t, client, req, []string{resp}, 120*time.Second, 30*time.Second) -} - -const imageEncoding = `iVBORw0KGgoAAAANSUhEUgAAANIAAAB4CAYAAACHHqzKAAAAAXNSR0IArs4c6QAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEb -AAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAANKgAwAEAAAAAQAA -AHgAAAAAXdsepgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6 -bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1z -eW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNv -bS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAg -PC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KGV7hBwAAQABJREFUeAGE3QfgX9P5OP6TIRKRncgmS6aR2DNCKEKLqqpRW9FWq0q1dEQparZKF7VK7aq99yZGSCRB -BhErk0Qmyf95nZOTfOqrv/9J7ud977nnPPt5zrz3Ntp0s61XrLnmmql58+Zp6dKlqUWLFmnZsmXp888/Tx07dkwLFy5MX3zxRT4aNWqUmjVrlho3bpzatGmT -Pvnkk5y/YsWKXHfttdfOv/VauSZNmuRj0aJFSX15cIAPruS3adOmafny5Uld5dDkXP05c+akTp06pTXWWCN99tlnacmSJQGnUVp77VbpvffeS126dM4wli4t -dK8RsJoHDvUXL16cy7du3TrjXrBgQS675prNUsu1WgV/AW/ZktSxQ4dMC37BXbDgs7Q4aG7cpHFq2bJlpo984EY/3vELB94k+eqjU36V1fz580OmSyO/WZZt -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` diff --git a/ollama/integration/llm_test.go b/ollama/integration/llm_test.go deleted file mode 100755 index 398e0a0..0000000 --- a/ollama/integration/llm_test.go +++ /dev/null @@ -1,47 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "testing" - "time" - - "github.com/ollama/ollama/api" -) - -// TODO - this would ideally be in the llm package, but that would require some refactoring of interfaces in the server -// package to avoid circular dependencies - -var ( - stream = false - req = [2]api.GenerateRequest{ - { - Model: "orca-mini", - Prompt: "why is the ocean blue?", - Stream: &stream, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "orca-mini", - Prompt: "what is the origin of the us thanksgiving holiday?", - Stream: &stream, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, - } - resp = [2][]string{ - {"sunlight"}, - {"england", "english", "massachusetts", "pilgrims"}, - } -) - -func TestIntegrationSimpleOrcaMini(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*120) - defer cancel() - GenerateTestHelper(ctx, t, req[0], resp[0]) -} diff --git a/ollama/integration/max_queue_test.go b/ollama/integration/max_queue_test.go deleted file mode 100755 index ec9e085..0000000 --- a/ollama/integration/max_queue_test.go +++ /dev/null @@ -1,120 +0,0 @@ -//go:build integration - -package integration - -import ( - "context" - "errors" - "log/slog" - "os" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/ollama/ollama/api" - "github.com/ollama/ollama/envconfig" -) - -func TestMaxQueue(t *testing.T) { - if os.Getenv("OLLAMA_TEST_EXISTING") != "" { - t.Skip("Max Queue test requires spawing a local server so we can adjust the queue size") - return - } - - // Note: This test can be quite slow when running in CPU mode, so keep the threadCount low unless your on GPU - // Also note that by default Darwin can't sustain > ~128 connections without adjusting limits - threadCount := 32 - if maxQueue := envconfig.MaxQueue(); maxQueue != 0 { - threadCount = int(maxQueue) - } else { - t.Setenv("OLLAMA_MAX_QUEUE", strconv.Itoa(threadCount)) - } - - req := api.GenerateRequest{ - Model: "orca-mini", - Prompt: "write a long historical fiction story about christopher columbus. use at least 10 facts from his actual journey", - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - } - resp := []string{"explore", "discover", "ocean"} - - // CPU mode takes much longer at the limit with a large queue setting - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - - require.NoError(t, PullIfMissing(ctx, client, req.Model)) - - // Context for the worker threads so we can shut them down - // embedCtx, embedCancel := context.WithCancel(ctx) - embedCtx := ctx - - var genwg sync.WaitGroup - go func() { - genwg.Add(1) - defer genwg.Done() - slog.Info("Starting generate request") - DoGenerate(ctx, t, client, req, resp, 45*time.Second, 5*time.Second) - slog.Info("generate completed") - }() - - // Give the generate a chance to get started before we start hammering on embed requests - time.Sleep(5 * time.Millisecond) - - threadCount += 10 // Add a few extra to ensure we push the queue past its limit - busyCount := 0 - resetByPeerCount := 0 - canceledCount := 0 - succesCount := 0 - counterMu := sync.Mutex{} - var embedwg sync.WaitGroup - for i := 0; i < threadCount; i++ { - go func(i int) { - embedwg.Add(1) - defer embedwg.Done() - slog.Info("embed started", "id", i) - embedReq := api.EmbeddingRequest{ - Model: req.Model, - Prompt: req.Prompt, - Options: req.Options, - } - // Fresh client for every request - client, _ = GetTestEndpoint() - - resp, genErr := client.Embeddings(embedCtx, &embedReq) - counterMu.Lock() - defer counterMu.Unlock() - switch { - case genErr == nil: - succesCount++ - require.Greater(t, len(resp.Embedding), 5) // somewhat arbitrary, but sufficient to be reasonable - case errors.Is(genErr, context.Canceled): - canceledCount++ - case strings.Contains(genErr.Error(), "busy"): - busyCount++ - case strings.Contains(genErr.Error(), "connection reset by peer"): - resetByPeerCount++ - default: - require.NoError(t, genErr, "%d request failed", i) - } - - slog.Info("embed finished", "id", i) - }(i) - } - genwg.Wait() - slog.Info("generate done, waiting for embeds") - embedwg.Wait() - - slog.Info("embeds completed", "success", succesCount, "busy", busyCount, "reset", resetByPeerCount, "canceled", canceledCount) - require.Equal(t, resetByPeerCount, 0, "Connections reset by peer, have you updated your fd and socket limits?") - require.True(t, busyCount > 0, "no requests hit busy error but some should have") - require.True(t, canceledCount == 0, "no requests should have been canceled due to timeout") - -} diff --git a/ollama/integration/utils_test.go b/ollama/integration/utils_test.go deleted file mode 100755 index a601099..0000000 --- a/ollama/integration/utils_test.go +++ /dev/null @@ -1,343 +0,0 @@ -//go:build integration - -package integration - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "log/slog" - "math/rand" - "net" - "net/http" - "net/url" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/ollama/ollama/api" - "github.com/ollama/ollama/app/lifecycle" - "github.com/stretchr/testify/require" -) - -func Init() { - lifecycle.InitLogging() -} - -func FindPort() string { - port := 0 - if a, err := net.ResolveTCPAddr("tcp", "localhost:0"); err == nil { - var l *net.TCPListener - if l, err = net.ListenTCP("tcp", a); err == nil { - port = l.Addr().(*net.TCPAddr).Port - l.Close() - } - } - if port == 0 { - port = rand.Intn(65535-49152) + 49152 // get a random port in the ephemeral range - } - return strconv.Itoa(port) -} - -func GetTestEndpoint() (*api.Client, string) { - defaultPort := "11434" - ollamaHost := os.Getenv("OLLAMA_HOST") - - scheme, hostport, ok := strings.Cut(ollamaHost, "://") - if !ok { - scheme, hostport = "http", ollamaHost - } - - // trim trailing slashes - hostport = strings.TrimRight(hostport, "/") - - host, port, err := net.SplitHostPort(hostport) - if err != nil { - host, port = "127.0.0.1", defaultPort - if ip := net.ParseIP(strings.Trim(hostport, "[]")); ip != nil { - host = ip.String() - } else if hostport != "" { - host = hostport - } - } - - if os.Getenv("OLLAMA_TEST_EXISTING") == "" && port == defaultPort { - port = FindPort() - } - - slog.Info("server connection", "host", host, "port", port) - - return api.NewClient( - &url.URL{ - Scheme: scheme, - Host: net.JoinHostPort(host, port), - }, - http.DefaultClient), fmt.Sprintf("%s:%s", host, port) -} - -var serverMutex sync.Mutex -var serverReady bool - -func startServer(t *testing.T, ctx context.Context, ollamaHost string) error { - // Make sure the server has been built - CLIName, err := filepath.Abs("../ollama") - if err != nil { - return err - } - - if runtime.GOOS == "windows" { - CLIName += ".exe" - } - _, err = os.Stat(CLIName) - if err != nil { - return fmt.Errorf("CLI missing, did you forget to build first? %w", err) - } - serverMutex.Lock() - defer serverMutex.Unlock() - if serverReady { - return nil - } - - if tmp := os.Getenv("OLLAMA_HOST"); tmp != ollamaHost { - slog.Info("setting env", "OLLAMA_HOST", ollamaHost) - t.Setenv("OLLAMA_HOST", ollamaHost) - } - - slog.Info("starting server", "url", ollamaHost) - done, err := lifecycle.SpawnServer(ctx, "../ollama") - if err != nil { - return fmt.Errorf("failed to start server: %w", err) - } - - go func() { - <-ctx.Done() - serverMutex.Lock() - defer serverMutex.Unlock() - exitCode := <-done - if exitCode > 0 { - slog.Warn("server failure", "exit", exitCode) - } - serverReady = false - }() - - // TODO wait only long enough for the server to be responsive... - time.Sleep(500 * time.Millisecond) - - serverReady = true - return nil -} - -func PullIfMissing(ctx context.Context, client *api.Client, modelName string) error { - slog.Info("checking status of model", "model", modelName) - showReq := &api.ShowRequest{Name: modelName} - - showCtx, cancel := context.WithDeadlineCause( - ctx, - time.Now().Add(10*time.Second), - fmt.Errorf("show for existing model %s took too long", modelName), - ) - defer cancel() - _, err := client.Show(showCtx, showReq) - var statusError api.StatusError - switch { - case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound: - break - case err != nil: - return err - default: - slog.Info("model already present", "model", modelName) - return nil - } - slog.Info("model missing", "model", modelName) - - stallDuration := 30 * time.Second // This includes checksum verification, which can take a while on larger models - stallTimer := time.NewTimer(stallDuration) - fn := func(resp api.ProgressResponse) error { - // fmt.Print(".") - if !stallTimer.Reset(stallDuration) { - return errors.New("stall was detected, aborting status reporting") - } - return nil - } - - stream := true - pullReq := &api.PullRequest{Name: modelName, Stream: &stream} - - var pullError error - - done := make(chan int) - go func() { - pullError = client.Pull(ctx, pullReq, fn) - done <- 0 - }() - - select { - case <-stallTimer.C: - return errors.New("download stalled") - case <-done: - return pullError - } -} - -var serverProcMutex sync.Mutex - -// Returns an Client, the testEndpoint, and a cleanup function, fails the test on errors -// Starts the server if needed -func InitServerConnection(ctx context.Context, t *testing.T) (*api.Client, string, func()) { - client, testEndpoint := GetTestEndpoint() - if os.Getenv("OLLAMA_TEST_EXISTING") == "" { - serverProcMutex.Lock() - fp, err := os.CreateTemp("", "ollama-server-*.log") - if err != nil { - t.Fatalf("failed to generate log file: %s", err) - } - lifecycle.ServerLogFile = fp.Name() - fp.Close() - require.NoError(t, startServer(t, ctx, testEndpoint)) - } - - return client, testEndpoint, func() { - if os.Getenv("OLLAMA_TEST_EXISTING") == "" { - defer serverProcMutex.Unlock() - if t.Failed() { - fp, err := os.Open(lifecycle.ServerLogFile) - if err != nil { - slog.Error("failed to open server log", "logfile", lifecycle.ServerLogFile, "error", err) - return - } - data, err := io.ReadAll(fp) - if err != nil { - slog.Error("failed to read server log", "logfile", lifecycle.ServerLogFile, "error", err) - return - } - slog.Warn("SERVER LOG FOLLOWS") - os.Stderr.Write(data) - slog.Warn("END OF SERVER") - } - err := os.Remove(lifecycle.ServerLogFile) - if err != nil && !os.IsNotExist(err) { - slog.Warn("failed to cleanup", "logfile", lifecycle.ServerLogFile, "error", err) - } - } - } -} - -func GenerateTestHelper(ctx context.Context, t *testing.T, genReq api.GenerateRequest, anyResp []string) { - client, _, cleanup := InitServerConnection(ctx, t) - defer cleanup() - require.NoError(t, PullIfMissing(ctx, client, genReq.Model)) - DoGenerate(ctx, t, client, genReq, anyResp, 30*time.Second, 10*time.Second) -} - -func DoGenerate(ctx context.Context, t *testing.T, client *api.Client, genReq api.GenerateRequest, anyResp []string, initialTimeout, streamTimeout time.Duration) { - stallTimer := time.NewTimer(initialTimeout) - var buf bytes.Buffer - fn := func(response api.GenerateResponse) error { - // fmt.Print(".") - buf.Write([]byte(response.Response)) - if !stallTimer.Reset(streamTimeout) { - return errors.New("stall was detected while streaming response, aborting") - } - return nil - } - - stream := true - genReq.Stream = &stream - done := make(chan int) - var genErr error - go func() { - genErr = client.Generate(ctx, &genReq, fn) - done <- 0 - }() - - select { - case <-stallTimer.C: - if buf.Len() == 0 { - t.Errorf("generate never started. Timed out after :%s", initialTimeout.String()) - } else { - t.Errorf("generate stalled. Response so far:%s", buf.String()) - } - case <-done: - require.NoError(t, genErr, "failed with %s request prompt %s ", genReq.Model, genReq.Prompt) - // Verify the response contains the expected data - response := buf.String() - atLeastOne := false - for _, resp := range anyResp { - if strings.Contains(strings.ToLower(response), resp) { - atLeastOne = true - break - } - } - require.True(t, atLeastOne, "none of %v found in %s", anyResp, response) - slog.Info("test pass", "model", genReq.Model, "prompt", genReq.Prompt, "contains", anyResp, "response", response) - case <-ctx.Done(): - t.Error("outer test context done while waiting for generate") - } -} - -// Generate a set of requests -// By default each request uses orca-mini as the model -func GenerateRequests() ([]api.GenerateRequest, [][]string) { - return []api.GenerateRequest{ - { - Model: "orca-mini", - Prompt: "why is the ocean blue?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "orca-mini", - Prompt: "why is the color of dirt brown?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "orca-mini", - Prompt: "what is the origin of the us thanksgiving holiday?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "orca-mini", - Prompt: "what is the origin of independence day?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, { - Model: "orca-mini", - Prompt: "what is the composition of air?", - Stream: &stream, - KeepAlive: &api.Duration{Duration: 10 * time.Second}, - Options: map[string]interface{}{ - "seed": 42, - "temperature": 0.0, - }, - }, - }, - [][]string{ - {"sunlight"}, - {"soil", "organic", "earth", "black", "tan"}, - {"england", "english", "massachusetts", "pilgrims", "british"}, - {"fourth", "july", "declaration", "independence"}, - {"nitrogen", "oxygen", "carbon", "dioxide"}, - } -} diff --git a/ollama/llm/ext_server/CMakeLists.txt b/ollama/llm/ext_server/CMakeLists.txt deleted file mode 100755 index bfc97c6..0000000 --- a/ollama/llm/ext_server/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -set(TARGET ollama_llama_server) -option(LLAMA_SERVER_VERBOSE "Build verbose logging option for Server" ON) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_executable(${TARGET} server.cpp utils.hpp json.hpp httplib.h) -install(TARGETS ${TARGET} RUNTIME) -target_compile_definitions(${TARGET} PRIVATE - SERVER_VERBOSE=$ -) -target_link_libraries(${TARGET} PRIVATE ggml llama common llava ${CMAKE_THREAD_LIBS_INIT}) -if (WIN32) - TARGET_LINK_LIBRARIES(${TARGET} PRIVATE ws2_32) -endif() -target_compile_features(${TARGET} PRIVATE cxx_std_11) \ No newline at end of file diff --git a/ollama/llm/ext_server/httplib.h b/ollama/llm/ext_server/httplib.h deleted file mode 100755 index 2874600..0000000 --- a/ollama/llm/ext_server/httplib.h +++ /dev/null @@ -1,8794 +0,0 @@ -// -// httplib.h -// -// Copyright (c) 2023 Yuji Hirose. All rights reserved. -// MIT License -// - -#ifndef CPPHTTPLIB_HTTPLIB_H -#define CPPHTTPLIB_HTTPLIB_H - -#define CPPHTTPLIB_VERSION "0.12.2" - -/* - * Configuration - */ - -#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND -#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT -#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5 -#endif - -#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND -#define CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND 300 -#endif - -#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND -#define CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_READ_TIMEOUT_SECOND -#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_READ_TIMEOUT_USECOND -#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_WRITE_TIMEOUT_SECOND -#define CPPHTTPLIB_WRITE_TIMEOUT_SECOND 5 -#endif - -#ifndef CPPHTTPLIB_WRITE_TIMEOUT_USECOND -#define CPPHTTPLIB_WRITE_TIMEOUT_USECOND 0 -#endif - -#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND -#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0 -#endif - -#ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND -#ifdef _WIN32 -#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 10000 -#else -#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 0 -#endif -#endif - -#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH -#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_HEADER_MAX_LENGTH -#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT -#define CPPHTTPLIB_REDIRECT_MAX_COUNT 20 -#endif - -#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT -#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024 -#endif - -#ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH -#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits::max)()) -#endif - -#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH -#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192 -#endif - -#ifndef CPPHTTPLIB_TCP_NODELAY -#define CPPHTTPLIB_TCP_NODELAY false -#endif - -#ifndef CPPHTTPLIB_RECV_BUFSIZ -#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u) -#endif - -#ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ -#define CPPHTTPLIB_COMPRESSION_BUFSIZ size_t(16384u) -#endif - -#ifndef CPPHTTPLIB_THREAD_POOL_COUNT -#define CPPHTTPLIB_THREAD_POOL_COUNT \ - ((std::max)(8u, std::thread::hardware_concurrency() > 0 \ - ? std::thread::hardware_concurrency() - 1 \ - : 0)) -#endif - -#ifndef CPPHTTPLIB_RECV_FLAGS -#define CPPHTTPLIB_RECV_FLAGS 0 -#endif - -#ifndef CPPHTTPLIB_SEND_FLAGS -#define CPPHTTPLIB_SEND_FLAGS 0 -#endif - -#ifndef CPPHTTPLIB_LISTEN_BACKLOG -#define CPPHTTPLIB_LISTEN_BACKLOG 5 -#endif - -/* - * Headers - */ - -#ifdef _WIN32 -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif //_CRT_SECURE_NO_WARNINGS - -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif //_CRT_NONSTDC_NO_DEPRECATE - -#if defined(_MSC_VER) -#if _MSC_VER < 1900 -#error Sorry, Visual Studio versions prior to 2015 are not supported -#endif - -#pragma comment(lib, "ws2_32.lib") - -#ifdef _WIN64 -using ssize_t = __int64; -#else -using ssize_t = long; -#endif -#endif // _MSC_VER - -#ifndef S_ISREG -#define S_ISREG(m) (((m)&S_IFREG) == S_IFREG) -#endif // S_ISREG - -#ifndef S_ISDIR -#define S_ISDIR(m) (((m)&S_IFDIR) == S_IFDIR) -#endif // S_ISDIR - -#ifndef NOMINMAX -#define NOMINMAX -#endif // NOMINMAX - -#include -#include -#include - -#ifndef WSA_FLAG_NO_HANDLE_INHERIT -#define WSA_FLAG_NO_HANDLE_INHERIT 0x80 -#endif - -#ifndef strcasecmp -#define strcasecmp _stricmp -#endif // strcasecmp - -using socket_t = SOCKET; -#ifdef CPPHTTPLIB_USE_POLL -#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout) -#endif - -#else // not _WIN32 - -#include -#ifndef _AIX -#include -#endif -#include -#include -#include -#ifdef __linux__ -#include -#endif -#include -#ifdef CPPHTTPLIB_USE_POLL -#include -#endif -#include -#include -#include -#include -#include -#include - -using socket_t = int; -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (-1) -#endif -#endif //_WIN32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -#ifdef _WIN32 -#include - -// these are defined in wincrypt.h and it breaks compilation if BoringSSL is -// used -#undef X509_NAME -#undef X509_CERT_PAIR -#undef X509_EXTENSIONS -#undef PKCS7_SIGNER_INFO - -#ifdef _MSC_VER -#pragma comment(lib, "crypt32.lib") -#pragma comment(lib, "cryptui.lib") -#endif -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#include -#if TARGET_OS_OSX -#include -#include -#endif // TARGET_OS_OSX -#endif // _WIN32 - -#include -#include -#include -#include - -#if defined(_WIN32) && defined(OPENSSL_USE_APPLINK) -#include -#endif - -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x1010100fL -#error Sorry, OpenSSL versions prior to 1.1.1 are not supported -#elif OPENSSL_VERSION_NUMBER < 0x30000000L -#define SSL_get1_peer_certificate SSL_get_peer_certificate -#endif - -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -#include -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -#include -#include -#endif - -/* - * Declaration - */ -namespace httplib { - -namespace detail { - -/* - * Backport std::make_unique from C++14. - * - * NOTE: This code came up with the following stackoverflow post: - * https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique - * - */ - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Args &&...args) { - return std::unique_ptr(new T(std::forward(args)...)); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(std::size_t n) { - typedef typename std::remove_extent::type RT; - return std::unique_ptr(new RT[n]); -} - -struct ci { - bool operator()(const std::string &s1, const std::string &s2) const { - return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), - s2.end(), - [](unsigned char c1, unsigned char c2) { - return ::tolower(c1) < ::tolower(c2); - }); - } -}; - -// This is based on -// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189". - -struct scope_exit { - explicit scope_exit(std::function &&f) - : exit_function(std::move(f)), execute_on_destruction{true} {} - - scope_exit(scope_exit &&rhs) - : exit_function(std::move(rhs.exit_function)), - execute_on_destruction{rhs.execute_on_destruction} { - rhs.release(); - } - - ~scope_exit() { - if (execute_on_destruction) { this->exit_function(); } - } - - void release() { this->execute_on_destruction = false; } - -private: - scope_exit(const scope_exit &) = delete; - void operator=(const scope_exit &) = delete; - scope_exit &operator=(scope_exit &&) = delete; - - std::function exit_function; - bool execute_on_destruction; -}; - -} // namespace detail - -using Headers = std::multimap; - -using Params = std::multimap; -using Match = std::smatch; - -using Progress = std::function; - -struct Response; -using ResponseHandler = std::function; - -struct MultipartFormData { - std::string name; - std::string content; - std::string filename; - std::string content_type; -}; -using MultipartFormDataItems = std::vector; -using MultipartFormDataMap = std::multimap; - -class DataSink { -public: - DataSink() : os(&sb_), sb_(*this) {} - - DataSink(const DataSink &) = delete; - DataSink &operator=(const DataSink &) = delete; - DataSink(DataSink &&) = delete; - DataSink &operator=(DataSink &&) = delete; - - std::function write; - std::function done; - std::function done_with_trailer; - std::ostream os; - -private: - class data_sink_streambuf : public std::streambuf { - public: - explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {} - - protected: - std::streamsize xsputn(const char *s, std::streamsize n) { - sink_.write(s, static_cast(n)); - return n; - } - - private: - DataSink &sink_; - }; - - data_sink_streambuf sb_; -}; - -using ContentProvider = - std::function; - -using ContentProviderWithoutLength = - std::function; - -using ContentProviderResourceReleaser = std::function; - -struct MultipartFormDataProvider { - std::string name; - ContentProviderWithoutLength provider; - std::string filename; - std::string content_type; -}; -using MultipartFormDataProviderItems = std::vector; - -using ContentReceiverWithProgress = - std::function; - -using ContentReceiver = - std::function; - -using MultipartContentHeader = - std::function; - -class ContentReader { -public: - using Reader = std::function; - using MultipartReader = std::function; - - ContentReader(Reader reader, MultipartReader multipart_reader) - : reader_(std::move(reader)), - multipart_reader_(std::move(multipart_reader)) {} - - bool operator()(MultipartContentHeader header, - ContentReceiver receiver) const { - return multipart_reader_(std::move(header), std::move(receiver)); - } - - bool operator()(ContentReceiver receiver) const { - return reader_(std::move(receiver)); - } - - Reader reader_; - MultipartReader multipart_reader_; -}; - -using Range = std::pair; -using Ranges = std::vector; - -struct Request { - std::string method; - std::string path; - Headers headers; - std::string body; - - std::string remote_addr; - int remote_port = -1; - std::string local_addr; - int local_port = -1; - - // for server - std::string version; - std::string target; - Params params; - MultipartFormDataMap files; - Ranges ranges; - Match matches; - - // for client - ResponseHandler response_handler; - ContentReceiverWithProgress content_receiver; - Progress progress; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - const SSL *ssl = nullptr; -#endif - - bool has_header(const std::string &key) const; - std::string get_header_value(const std::string &key, size_t id = 0) const; - template - T get_header_value(const std::string &key, size_t id = 0) const; - size_t get_header_value_count(const std::string &key) const; - void set_header(const std::string &key, const std::string &val); - - bool has_param(const std::string &key) const; - std::string get_param_value(const std::string &key, size_t id = 0) const; - size_t get_param_value_count(const std::string &key) const; - - bool is_multipart_form_data() const; - - bool has_file(const std::string &key) const; - MultipartFormData get_file_value(const std::string &key) const; - std::vector get_file_values(const std::string &key) const; - - // private members... - size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT; - size_t content_length_ = 0; - ContentProvider content_provider_; - bool is_chunked_content_provider_ = false; - size_t authorization_count_ = 0; -}; - -struct Response { - std::string version; - int status = -1; - std::string reason; - Headers headers; - std::string body; - std::string location; // Redirect location - - bool has_header(const std::string &key) const; - std::string get_header_value(const std::string &key, size_t id = 0) const; - template - T get_header_value(const std::string &key, size_t id = 0) const; - size_t get_header_value_count(const std::string &key) const; - void set_header(const std::string &key, const std::string &val); - - void set_redirect(const std::string &url, int status = 302); - void set_content(const char *s, size_t n, const std::string &content_type); - void set_content(const std::string &s, const std::string &content_type); - - void set_content_provider( - size_t length, const std::string &content_type, ContentProvider provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - void set_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - void set_chunked_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser = nullptr); - - Response() = default; - Response(const Response &) = default; - Response &operator=(const Response &) = default; - Response(Response &&) = default; - Response &operator=(Response &&) = default; - ~Response() { - if (content_provider_resource_releaser_) { - content_provider_resource_releaser_(content_provider_success_); - } - } - - // private members... - size_t content_length_ = 0; - ContentProvider content_provider_; - ContentProviderResourceReleaser content_provider_resource_releaser_; - bool is_chunked_content_provider_ = false; - bool content_provider_success_ = false; -}; - -class Stream { -public: - virtual ~Stream() = default; - - virtual bool is_readable() const = 0; - virtual bool is_writable() const = 0; - - virtual ssize_t read(char *ptr, size_t size) = 0; - virtual ssize_t write(const char *ptr, size_t size) = 0; - virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0; - virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0; - virtual socket_t socket() const = 0; - - template - ssize_t write_format(const char *fmt, const Args &...args); - ssize_t write(const char *ptr); - ssize_t write(const std::string &s); -}; - -class TaskQueue { -public: - TaskQueue() = default; - virtual ~TaskQueue() = default; - - virtual void enqueue(std::function fn) = 0; - virtual void shutdown() = 0; - - virtual void on_idle() {} -}; - -class ThreadPool : public TaskQueue { -public: - explicit ThreadPool(size_t n) : shutdown_(false) { - while (n) { - threads_.emplace_back(worker(*this)); - n--; - } - } - - ThreadPool(const ThreadPool &) = delete; - ~ThreadPool() override = default; - - void enqueue(std::function fn) override { - { - std::unique_lock lock(mutex_); - jobs_.push_back(std::move(fn)); - } - - cond_.notify_one(); - } - - void shutdown() override { - // Stop all worker threads... - { - std::unique_lock lock(mutex_); - shutdown_ = true; - } - - cond_.notify_all(); - - // Join... - for (auto &t : threads_) { - t.join(); - } - } - -private: - struct worker { - explicit worker(ThreadPool &pool) : pool_(pool) {} - - void operator()() { - for (;;) { - std::function fn; - { - std::unique_lock lock(pool_.mutex_); - - pool_.cond_.wait( - lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; }); - - if (pool_.shutdown_ && pool_.jobs_.empty()) { break; } - - fn = std::move(pool_.jobs_.front()); - pool_.jobs_.pop_front(); - } - - assert(true == static_cast(fn)); - fn(); - } - } - - ThreadPool &pool_; - }; - friend struct worker; - - std::vector threads_; - std::list> jobs_; - - bool shutdown_; - - std::condition_variable cond_; - std::mutex mutex_; -}; - -using Logger = std::function; - -using SocketOptions = std::function; - -void default_socket_options(socket_t sock); - -class Server { -public: - using Handler = std::function; - - using ExceptionHandler = - std::function; - - enum class HandlerResponse { - Handled, - Unhandled, - }; - using HandlerWithResponse = - std::function; - - using HandlerWithContentReader = std::function; - - using Expect100ContinueHandler = - std::function; - - Server(); - - virtual ~Server(); - - virtual bool is_valid() const; - - Server &Get(const std::string &pattern, Handler handler); - Server &Post(const std::string &pattern, Handler handler); - Server &Post(const std::string &pattern, HandlerWithContentReader handler); - Server &Put(const std::string &pattern, Handler handler); - Server &Put(const std::string &pattern, HandlerWithContentReader handler); - Server &Patch(const std::string &pattern, Handler handler); - Server &Patch(const std::string &pattern, HandlerWithContentReader handler); - Server &Delete(const std::string &pattern, Handler handler); - Server &Delete(const std::string &pattern, HandlerWithContentReader handler); - Server &Options(const std::string &pattern, Handler handler); - - bool set_base_dir(const std::string &dir, - const std::string &mount_point = std::string()); - bool set_mount_point(const std::string &mount_point, const std::string &dir, - Headers headers = Headers()); - bool remove_mount_point(const std::string &mount_point); - Server &set_file_extension_and_mimetype_mapping(const std::string &ext, - const std::string &mime); - Server &set_file_request_handler(Handler handler); - - Server &set_error_handler(HandlerWithResponse handler); - Server &set_error_handler(Handler handler); - Server &set_exception_handler(ExceptionHandler handler); - Server &set_pre_routing_handler(HandlerWithResponse handler); - Server &set_post_routing_handler(Handler handler); - - Server &set_expect_100_continue_handler(Expect100ContinueHandler handler); - Server &set_logger(Logger logger); - - Server &set_address_family(int family); - Server &set_tcp_nodelay(bool on); - Server &set_socket_options(SocketOptions socket_options); - - Server &set_default_headers(Headers headers); - - Server &set_keep_alive_max_count(size_t count); - Server &set_keep_alive_timeout(time_t sec); - - Server &set_read_timeout(time_t sec, time_t usec = 0); - template - Server &set_read_timeout(const std::chrono::duration &duration); - - Server &set_write_timeout(time_t sec, time_t usec = 0); - template - Server &set_write_timeout(const std::chrono::duration &duration); - - Server &set_idle_interval(time_t sec, time_t usec = 0); - template - Server &set_idle_interval(const std::chrono::duration &duration); - - Server &set_payload_max_length(size_t length); - - bool bind_to_port(const std::string &host, int port, int socket_flags = 0); - int bind_to_any_port(const std::string &host, int socket_flags = 0); - bool listen_after_bind(); - - bool listen(const std::string &host, int port, int socket_flags = 0); - - bool is_running() const; - void wait_until_ready() const; - void stop(); - - std::function new_task_queue; - -protected: - bool process_request(Stream &strm, bool close_connection, - bool &connection_closed, - const std::function &setup_request); - - std::atomic svr_sock_{INVALID_SOCKET}; - size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT; - time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND; - time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND; - time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND; - time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND; - time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND; - time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND; - time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND; - size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH; - -private: - using Handlers = std::vector>; - using HandlersForContentReader = - std::vector>; - - socket_t create_server_socket(const std::string &host, int port, - int socket_flags, - SocketOptions socket_options) const; - int bind_internal(const std::string &host, int port, int socket_flags); - bool listen_internal(); - - bool routing(Request &req, Response &res, Stream &strm); - bool handle_file_request(const Request &req, Response &res, - bool head = false); - bool dispatch_request(Request &req, Response &res, const Handlers &handlers); - bool - dispatch_request_for_content_reader(Request &req, Response &res, - ContentReader content_reader, - const HandlersForContentReader &handlers); - - bool parse_request_line(const char *s, Request &req); - void apply_ranges(const Request &req, Response &res, - std::string &content_type, std::string &boundary); - bool write_response(Stream &strm, bool close_connection, const Request &req, - Response &res); - bool write_response_with_content(Stream &strm, bool close_connection, - const Request &req, Response &res); - bool write_response_core(Stream &strm, bool close_connection, - const Request &req, Response &res, - bool need_apply_ranges); - bool write_content_with_provider(Stream &strm, const Request &req, - Response &res, const std::string &boundary, - const std::string &content_type); - bool read_content(Stream &strm, Request &req, Response &res); - bool - read_content_with_content_receiver(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver); - bool read_content_core(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver); - - virtual bool process_and_close_socket(socket_t sock); - - struct MountPointEntry { - std::string mount_point; - std::string base_dir; - Headers headers; - }; - std::vector base_dirs_; - - std::atomic is_running_{false}; - std::atomic done_{false}; - std::map file_extension_and_mimetype_map_; - Handler file_request_handler_; - Handlers get_handlers_; - Handlers post_handlers_; - HandlersForContentReader post_handlers_for_content_reader_; - Handlers put_handlers_; - HandlersForContentReader put_handlers_for_content_reader_; - Handlers patch_handlers_; - HandlersForContentReader patch_handlers_for_content_reader_; - Handlers delete_handlers_; - HandlersForContentReader delete_handlers_for_content_reader_; - Handlers options_handlers_; - HandlerWithResponse error_handler_; - ExceptionHandler exception_handler_; - HandlerWithResponse pre_routing_handler_; - Handler post_routing_handler_; - Logger logger_; - Expect100ContinueHandler expect_100_continue_handler_; - - int address_family_ = AF_UNSPEC; - bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; - SocketOptions socket_options_ = default_socket_options; - - Headers default_headers_; -}; - -enum class Error { - Success = 0, - Unknown, - Connection, - BindIPAddress, - Read, - Write, - ExceedRedirectCount, - Canceled, - SSLConnection, - SSLLoadingCerts, - SSLServerVerification, - UnsupportedMultipartBoundaryChars, - Compression, - ConnectionTimeout, - - // For internal use only - SSLPeerCouldBeClosed_, -}; - -std::string to_string(const Error error); - -std::ostream &operator<<(std::ostream &os, const Error &obj); - -class Result { -public: - Result(std::unique_ptr &&res, Error err, - Headers &&request_headers = Headers{}) - : res_(std::move(res)), err_(err), - request_headers_(std::move(request_headers)) {} - // Response - operator bool() const { return res_ != nullptr; } - bool operator==(std::nullptr_t) const { return res_ == nullptr; } - bool operator!=(std::nullptr_t) const { return res_ != nullptr; } - const Response &value() const { return *res_; } - Response &value() { return *res_; } - const Response &operator*() const { return *res_; } - Response &operator*() { return *res_; } - const Response *operator->() const { return res_.get(); } - Response *operator->() { return res_.get(); } - - // Error - Error error() const { return err_; } - - // Request Headers - bool has_request_header(const std::string &key) const; - std::string get_request_header_value(const std::string &key, - size_t id = 0) const; - template - T get_request_header_value(const std::string &key, size_t id = 0) const; - size_t get_request_header_value_count(const std::string &key) const; - -private: - std::unique_ptr res_; - Error err_; - Headers request_headers_; -}; - -class ClientImpl { -public: - explicit ClientImpl(const std::string &host); - - explicit ClientImpl(const std::string &host, int port); - - explicit ClientImpl(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - virtual ~ClientImpl(); - - virtual bool is_valid() const; - - Result Get(const std::string &path); - Result Get(const std::string &path, const Headers &headers); - Result Get(const std::string &path, Progress progress); - Result Get(const std::string &path, const Headers &headers, - Progress progress); - Result Get(const std::string &path, ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const std::string &path, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress); - - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress = nullptr); - - Result Head(const std::string &path); - Result Head(const std::string &path, const Headers &headers); - - Result Post(const std::string &path); - Result Post(const std::string &path, const Headers &headers); - Result Post(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Post(const std::string &path, const std::string &body, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Params ¶ms); - Result Post(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Post(const std::string &path, const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Put(const std::string &path); - Result Put(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Put(const std::string &path, const std::string &body, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Put(const std::string &path, size_t content_length, - ContentProvider content_provider, const std::string &content_type); - Result Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Params ¶ms); - Result Put(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Put(const std::string &path, const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Patch(const std::string &path); - Result Patch(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const std::string &body, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - - Result Delete(const std::string &path); - Result Delete(const std::string &path, const Headers &headers); - Result Delete(const std::string &path, const char *body, - size_t content_length, const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Delete(const std::string &path, const std::string &body, - const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - - Result Options(const std::string &path); - Result Options(const std::string &path, const Headers &headers); - - bool send(Request &req, Response &res, Error &error); - Result send(const Request &req); - - size_t is_socket_open() const; - - socket_t socket() const; - - void stop(); - - void set_hostname_addr_map(std::map addr_map); - - void set_default_headers(Headers headers); - - void set_address_family(int family); - void set_tcp_nodelay(bool on); - void set_socket_options(SocketOptions socket_options); - - void set_connection_timeout(time_t sec, time_t usec = 0); - template - void - set_connection_timeout(const std::chrono::duration &duration); - - void set_read_timeout(time_t sec, time_t usec = 0); - template - void set_read_timeout(const std::chrono::duration &duration); - - void set_write_timeout(time_t sec, time_t usec = 0); - template - void set_write_timeout(const std::chrono::duration &duration); - - void set_basic_auth(const std::string &username, const std::string &password); - void set_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const std::string &username, - const std::string &password); -#endif - - void set_keep_alive(bool on); - void set_follow_location(bool on); - - void set_url_encode(bool on); - - void set_compress(bool on); - - void set_decompress(bool on); - - void set_interface(const std::string &intf); - - void set_proxy(const std::string &host, int port); - void set_proxy_basic_auth(const std::string &username, - const std::string &password); - void set_proxy_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const std::string &username, - const std::string &password); -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path = std::string()); - void set_ca_cert_store(X509_STORE *ca_cert_store); -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void enable_server_certificate_verification(bool enabled); -#endif - - void set_logger(Logger logger); - -protected: - struct Socket { - socket_t sock = INVALID_SOCKET; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - SSL *ssl = nullptr; -#endif - - bool is_open() const { return sock != INVALID_SOCKET; } - }; - - virtual bool create_and_connect_socket(Socket &socket, Error &error); - - // All of: - // shutdown_ssl - // shutdown_socket - // close_socket - // should ONLY be called when socket_mutex_ is locked. - // Also, shutdown_ssl and close_socket should also NOT be called concurrently - // with a DIFFERENT thread sending requests using that socket. - virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully); - void shutdown_socket(Socket &socket); - void close_socket(Socket &socket); - - bool process_request(Stream &strm, Request &req, Response &res, - bool close_connection, Error &error); - - bool write_content_with_provider(Stream &strm, const Request &req, - Error &error); - - void copy_settings(const ClientImpl &rhs); - - // Socket endpoint information - const std::string host_; - const int port_; - const std::string host_and_port_; - - // Current open socket - Socket socket_; - mutable std::mutex socket_mutex_; - std::recursive_mutex request_mutex_; - - // These are all protected under socket_mutex - size_t socket_requests_in_flight_ = 0; - std::thread::id socket_requests_are_from_thread_ = std::thread::id(); - bool socket_should_be_closed_when_request_is_done_ = false; - - // Hostname-IP map - std::map addr_map_; - - // Default headers - Headers default_headers_; - - // Settings - std::string client_cert_path_; - std::string client_key_path_; - - time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND; - time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND; - time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND; - time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND; - time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND; - time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND; - - std::string basic_auth_username_; - std::string basic_auth_password_; - std::string bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string digest_auth_username_; - std::string digest_auth_password_; -#endif - - bool keep_alive_ = false; - bool follow_location_ = false; - - bool url_encode_ = true; - - int address_family_ = AF_UNSPEC; - bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; - SocketOptions socket_options_ = nullptr; - - bool compress_ = false; - bool decompress_ = true; - - std::string interface_; - - std::string proxy_host_; - int proxy_port_ = -1; - - std::string proxy_basic_auth_username_; - std::string proxy_basic_auth_password_; - std::string proxy_bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string proxy_digest_auth_username_; - std::string proxy_digest_auth_password_; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - std::string ca_cert_file_path_; - std::string ca_cert_dir_path_; - - X509_STORE *ca_cert_store_ = nullptr; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - bool server_certificate_verification_ = true; -#endif - - Logger logger_; - -private: - bool send_(Request &req, Response &res, Error &error); - Result send_(Request &&req); - - socket_t create_client_socket(Error &error) const; - bool read_response_line(Stream &strm, const Request &req, Response &res); - bool write_request(Stream &strm, Request &req, bool close_connection, - Error &error); - bool redirect(Request &req, Response &res, Error &error); - bool handle_request(Stream &strm, Request &req, Response &res, - bool close_connection, Error &error); - std::unique_ptr send_with_content_provider( - Request &req, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type, Error &error); - Result send_with_content_provider( - const std::string &method, const std::string &path, - const Headers &headers, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type); - ContentProviderWithoutLength get_multipart_content_provider( - const std::string &boundary, const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - std::string adjust_host_string(const std::string &host) const; - - virtual bool process_socket(const Socket &socket, - std::function callback); - virtual bool is_ssl() const; -}; - -class Client { -public: - // Universal interface - explicit Client(const std::string &scheme_host_port); - - explicit Client(const std::string &scheme_host_port, - const std::string &client_cert_path, - const std::string &client_key_path); - - // HTTP only interface - explicit Client(const std::string &host, int port); - - explicit Client(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - Client(Client &&) = default; - - ~Client(); - - bool is_valid() const; - - Result Get(const std::string &path); - Result Get(const std::string &path, const Headers &headers); - Result Get(const std::string &path, Progress progress); - Result Get(const std::string &path, const Headers &headers, - Progress progress); - Result Get(const std::string &path, ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const std::string &path, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver); - Result Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress); - Result Get(const std::string &path, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress); - - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Get(const std::string &path, const Params ¶ms, - const Headers &headers, ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress = nullptr); - - Result Head(const std::string &path); - Result Head(const std::string &path, const Headers &headers); - - Result Post(const std::string &path); - Result Post(const std::string &path, const Headers &headers); - Result Post(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Post(const std::string &path, const std::string &body, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Post(const std::string &path, const Params ¶ms); - Result Post(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Post(const std::string &path, const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Put(const std::string &path); - Result Put(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, const char *body, - size_t content_length, const std::string &content_type); - Result Put(const std::string &path, const std::string &body, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Put(const std::string &path, size_t content_length, - ContentProvider content_provider, const std::string &content_type); - Result Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Put(const std::string &path, const Params ¶ms); - Result Put(const std::string &path, const Headers &headers, - const Params ¶ms); - Result Put(const std::string &path, const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items); - - Result Patch(const std::string &path); - Result Patch(const std::string &path, const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Patch(const std::string &path, const std::string &body, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - Result Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - size_t content_length, ContentProvider content_provider, - const std::string &content_type); - Result Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type); - - Result Delete(const std::string &path); - Result Delete(const std::string &path, const Headers &headers); - Result Delete(const std::string &path, const char *body, - size_t content_length, const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type); - Result Delete(const std::string &path, const std::string &body, - const std::string &content_type); - Result Delete(const std::string &path, const Headers &headers, - const std::string &body, const std::string &content_type); - - Result Options(const std::string &path); - Result Options(const std::string &path, const Headers &headers); - - bool send(Request &req, Response &res, Error &error); - Result send(const Request &req); - - size_t is_socket_open() const; - - socket_t socket() const; - - void stop(); - - void set_hostname_addr_map(std::map addr_map); - - void set_default_headers(Headers headers); - - void set_address_family(int family); - void set_tcp_nodelay(bool on); - void set_socket_options(SocketOptions socket_options); - - void set_connection_timeout(time_t sec, time_t usec = 0); - template - void - set_connection_timeout(const std::chrono::duration &duration); - - void set_read_timeout(time_t sec, time_t usec = 0); - template - void set_read_timeout(const std::chrono::duration &duration); - - void set_write_timeout(time_t sec, time_t usec = 0); - template - void set_write_timeout(const std::chrono::duration &duration); - - void set_basic_auth(const std::string &username, const std::string &password); - void set_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const std::string &username, - const std::string &password); -#endif - - void set_keep_alive(bool on); - void set_follow_location(bool on); - - void set_url_encode(bool on); - - void set_compress(bool on); - - void set_decompress(bool on); - - void set_interface(const std::string &intf); - - void set_proxy(const std::string &host, int port); - void set_proxy_basic_auth(const std::string &username, - const std::string &password); - void set_proxy_bearer_token_auth(const std::string &token); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const std::string &username, - const std::string &password); -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void enable_server_certificate_verification(bool enabled); -#endif - - void set_logger(Logger logger); - - // SSL -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path = std::string()); - - void set_ca_cert_store(X509_STORE *ca_cert_store); - - long get_openssl_verify_result() const; - - SSL_CTX *ssl_context() const; -#endif - -private: - std::unique_ptr cli_; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - bool is_ssl_ = false; -#endif -}; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -class SSLServer : public Server { -public: - SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path = nullptr, - const char *client_ca_cert_dir_path = nullptr, - const char *private_key_password = nullptr); - - SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store = nullptr); - - SSLServer( - const std::function &setup_ssl_ctx_callback); - - ~SSLServer() override; - - bool is_valid() const override; - - SSL_CTX *ssl_context() const; - -private: - bool process_and_close_socket(socket_t sock) override; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; -}; - -class SSLClient : public ClientImpl { -public: - explicit SSLClient(const std::string &host); - - explicit SSLClient(const std::string &host, int port); - - explicit SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path); - - explicit SSLClient(const std::string &host, int port, X509 *client_cert, - EVP_PKEY *client_key); - - ~SSLClient() override; - - bool is_valid() const override; - - void set_ca_cert_store(X509_STORE *ca_cert_store); - - long get_openssl_verify_result() const; - - SSL_CTX *ssl_context() const; - -private: - bool create_and_connect_socket(Socket &socket, Error &error) override; - void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override; - void shutdown_ssl_impl(Socket &socket, bool shutdown_socket); - - bool process_socket(const Socket &socket, - std::function callback) override; - bool is_ssl() const override; - - bool connect_with_proxy(Socket &sock, Response &res, bool &success, - Error &error); - bool initialize_ssl(Socket &socket, Error &error); - - bool load_certs(); - - bool verify_host(X509 *server_cert) const; - bool verify_host_with_subject_alt_name(X509 *server_cert) const; - bool verify_host_with_common_name(X509 *server_cert) const; - bool check_host_name(const char *pattern, size_t pattern_len) const; - - SSL_CTX *ctx_; - std::mutex ctx_mutex_; - std::once_flag initialize_cert_; - - std::vector host_components_; - - long verify_result_ = 0; - - friend class ClientImpl; -}; -#endif - -/* - * Implementation of template methods. - */ - -namespace detail { - -template -inline void duration_to_sec_and_usec(const T &duration, U callback) { - auto sec = std::chrono::duration_cast(duration).count(); - auto usec = std::chrono::duration_cast( - duration - std::chrono::seconds(sec)) - .count(); - callback(static_cast(sec), static_cast(usec)); -} - -template -inline T get_header_value(const Headers & /*headers*/, - const std::string & /*key*/, size_t /*id*/ = 0, - uint64_t /*def*/ = 0) {} - -template <> -inline uint64_t get_header_value(const Headers &headers, - const std::string &key, size_t id, - uint64_t def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { - return std::strtoull(it->second.data(), nullptr, 10); - } - return def; -} - -} // namespace detail - -template -inline T Request::get_header_value(const std::string &key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); -} - -template -inline T Response::get_header_value(const std::string &key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); -} - -template -inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { - const auto bufsiz = 2048; - std::array buf{}; - - auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); - if (sn <= 0) { return sn; } - - auto n = static_cast(sn); - - if (n >= buf.size() - 1) { - std::vector glowable_buf(buf.size()); - - while (n >= glowable_buf.size() - 1) { - glowable_buf.resize(glowable_buf.size() * 2); - n = static_cast( - snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); - } - return write(&glowable_buf[0], n); - } else { - return write(buf.data(), n); - } -} - -inline void default_socket_options(socket_t sock) { - int yes = 1; -#ifdef _WIN32 - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); - setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, - reinterpret_cast(&yes), sizeof(yes)); -#else -#ifdef SO_REUSEPORT - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&yes), - sizeof(yes)); -#else - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); -#endif -#endif -} - -template -inline Server & -Server::set_read_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); - return *this; -} - -template -inline Server & -Server::set_write_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); - return *this; -} - -template -inline Server & -Server::set_idle_interval(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); - return *this; -} - -inline std::string to_string(const Error error) { - switch (error) { - case Error::Success: return "Success (no error)"; - case Error::Connection: return "Could not establish connection"; - case Error::BindIPAddress: return "Failed to bind IP address"; - case Error::Read: return "Failed to read connection"; - case Error::Write: return "Failed to write connection"; - case Error::ExceedRedirectCount: return "Maximum redirect count exceeded"; - case Error::Canceled: return "Connection handling canceled"; - case Error::SSLConnection: return "SSL connection failed"; - case Error::SSLLoadingCerts: return "SSL certificate loading failed"; - case Error::SSLServerVerification: return "SSL server verification failed"; - case Error::UnsupportedMultipartBoundaryChars: - return "Unsupported HTTP multipart boundary characters"; - case Error::Compression: return "Compression failed"; - case Error::ConnectionTimeout: return "Connection timed out"; - case Error::Unknown: return "Unknown"; - default: break; - } - - return "Invalid"; -} - -inline std::ostream &operator<<(std::ostream &os, const Error &obj) { - os << to_string(obj); - os << " (" << static_cast::type>(obj) << ')'; - return os; -} - -template -inline T Result::get_request_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(request_headers_, key, id, 0); -} - -template -inline void ClientImpl::set_connection_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { - set_connection_timeout(sec, usec); - }); -} - -template -inline void ClientImpl::set_read_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); -} - -template -inline void ClientImpl::set_write_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); -} - -template -inline void Client::set_connection_timeout( - const std::chrono::duration &duration) { - cli_->set_connection_timeout(duration); -} - -template -inline void -Client::set_read_timeout(const std::chrono::duration &duration) { - cli_->set_read_timeout(duration); -} - -template -inline void -Client::set_write_timeout(const std::chrono::duration &duration) { - cli_->set_write_timeout(duration); -} - -/* - * Forward declarations and types that will be part of the .h file if split into - * .h + .cc. - */ - -std::string hosted_at(const std::string &hostname); - -void hosted_at(const std::string &hostname, std::vector &addrs); - -std::string append_query_params(const std::string &path, const Params ¶ms); - -std::pair make_range_header(Ranges ranges); - -std::pair -make_basic_authentication_header(const std::string &username, - const std::string &password, - bool is_proxy = false); - -namespace detail { - -std::string encode_query_param(const std::string &value); - -std::string decode_url(const std::string &s, bool convert_plus_to_space); - -void read_file(const std::string &path, std::string &out); - -std::string trim_copy(const std::string &s); - -void split(const char *b, const char *e, char d, - std::function fn); - -bool process_client_socket(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, - std::function callback); - -socket_t create_client_socket( - const std::string &host, const std::string &ip, int port, - int address_family, bool tcp_nodelay, SocketOptions socket_options, - time_t connection_timeout_sec, time_t connection_timeout_usec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, const std::string &intf, Error &error); - -const char *get_header_value(const Headers &headers, const std::string &key, - size_t id = 0, const char *def = nullptr); - -std::string params_to_query_str(const Params ¶ms); - -void parse_query_text(const std::string &s, Params ¶ms); - -bool parse_multipart_boundary(const std::string &content_type, - std::string &boundary); - -bool parse_range_header(const std::string &s, Ranges &ranges); - -int close_socket(socket_t sock); - -ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags); - -ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags); - -enum class EncodingType { None = 0, Gzip, Brotli }; - -EncodingType encoding_type(const Request &req, const Response &res); - -class BufferStream : public Stream { -public: - BufferStream() = default; - ~BufferStream() override = default; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - - const std::string &get_buffer() const; - -private: - std::string buffer; - size_t position = 0; -}; - -class compressor { -public: - virtual ~compressor() = default; - - typedef std::function Callback; - virtual bool compress(const char *data, size_t data_length, bool last, - Callback callback) = 0; -}; - -class decompressor { -public: - virtual ~decompressor() = default; - - virtual bool is_valid() const = 0; - - typedef std::function Callback; - virtual bool decompress(const char *data, size_t data_length, - Callback callback) = 0; -}; - -class nocompressor : public compressor { -public: - virtual ~nocompressor() = default; - - bool compress(const char *data, size_t data_length, bool /*last*/, - Callback callback) override; -}; - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -class gzip_compressor : public compressor { -public: - gzip_compressor(); - ~gzip_compressor(); - - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override; - -private: - bool is_valid_ = false; - z_stream strm_; -}; - -class gzip_decompressor : public decompressor { -public: - gzip_decompressor(); - ~gzip_decompressor(); - - bool is_valid() const override; - - bool decompress(const char *data, size_t data_length, - Callback callback) override; - -private: - bool is_valid_ = false; - z_stream strm_; -}; -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -class brotli_compressor : public compressor { -public: - brotli_compressor(); - ~brotli_compressor(); - - bool compress(const char *data, size_t data_length, bool last, - Callback callback) override; - -private: - BrotliEncoderState *state_ = nullptr; -}; - -class brotli_decompressor : public decompressor { -public: - brotli_decompressor(); - ~brotli_decompressor(); - - bool is_valid() const override; - - bool decompress(const char *data, size_t data_length, - Callback callback) override; - -private: - BrotliDecoderResult decoder_r; - BrotliDecoderState *decoder_s = nullptr; -}; -#endif - -// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer` -// to store data. The call can set memory on stack for performance. -class stream_line_reader { -public: - stream_line_reader(Stream &strm, char *fixed_buffer, - size_t fixed_buffer_size); - const char *ptr() const; - size_t size() const; - bool end_with_crlf() const; - bool getline(); - -private: - void append(char c); - - Stream &strm_; - char *fixed_buffer_; - const size_t fixed_buffer_size_; - size_t fixed_buffer_used_size_ = 0; - std::string glowable_buffer_; -}; - -} // namespace detail - -// ---------------------------------------------------------------------------- - -/* - * Implementation that will be part of the .cc file if split into .h + .cc. - */ - -namespace detail { - -inline bool is_hex(char c, int &v) { - if (0x20 <= c && isdigit(c)) { - v = c - '0'; - return true; - } else if ('A' <= c && c <= 'F') { - v = c - 'A' + 10; - return true; - } else if ('a' <= c && c <= 'f') { - v = c - 'a' + 10; - return true; - } - return false; -} - -inline bool from_hex_to_i(const std::string &s, size_t i, size_t cnt, - int &val) { - if (i >= s.size()) { return false; } - - val = 0; - for (; cnt; i++, cnt--) { - if (!s[i]) { return false; } - int v = 0; - if (is_hex(s[i], v)) { - val = val * 16 + v; - } else { - return false; - } - } - return true; -} - -inline std::string from_i_to_hex(size_t n) { - const char *charset = "0123456789abcdef"; - std::string ret; - do { - ret = charset[n & 15] + ret; - n >>= 4; - } while (n > 0); - return ret; -} - -inline size_t to_utf8(int code, char *buff) { - if (code < 0x0080) { - buff[0] = (code & 0x7F); - return 1; - } else if (code < 0x0800) { - buff[0] = static_cast(0xC0 | ((code >> 6) & 0x1F)); - buff[1] = static_cast(0x80 | (code & 0x3F)); - return 2; - } else if (code < 0xD800) { - buff[0] = static_cast(0xE0 | ((code >> 12) & 0xF)); - buff[1] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[2] = static_cast(0x80 | (code & 0x3F)); - return 3; - } else if (code < 0xE000) { // D800 - DFFF is invalid... - return 0; - } else if (code < 0x10000) { - buff[0] = static_cast(0xE0 | ((code >> 12) & 0xF)); - buff[1] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[2] = static_cast(0x80 | (code & 0x3F)); - return 3; - } else if (code < 0x110000) { - buff[0] = static_cast(0xF0 | ((code >> 18) & 0x7)); - buff[1] = static_cast(0x80 | ((code >> 12) & 0x3F)); - buff[2] = static_cast(0x80 | ((code >> 6) & 0x3F)); - buff[3] = static_cast(0x80 | (code & 0x3F)); - return 4; - } - - // NOTREACHED - return 0; -} - -// NOTE: This code came up with the following stackoverflow post: -// https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c -inline std::string base64_encode(const std::string &in) { - static const auto lookup = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - std::string out; - out.reserve(in.size()); - - int val = 0; - int valb = -6; - - for (auto c : in) { - val = (val << 8) + static_cast(c); - valb += 8; - while (valb >= 0) { - out.push_back(lookup[(val >> valb) & 0x3F]); - valb -= 6; - } - } - - if (valb > -6) { out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]); } - - while (out.size() % 4) { - out.push_back('='); - } - - return out; -} - -inline bool is_file(const std::string &path) { -#ifdef _WIN32 - return _access_s(path.c_str(), 0) == 0; -#else - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode); -#endif -} - -inline bool is_dir(const std::string &path) { - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode); -} - -inline bool is_valid_path(const std::string &path) { - size_t level = 0; - size_t i = 0; - - // Skip slash - while (i < path.size() && path[i] == '/') { - i++; - } - - while (i < path.size()) { - // Read component - auto beg = i; - while (i < path.size() && path[i] != '/') { - i++; - } - - auto len = i - beg; - assert(len > 0); - - if (!path.compare(beg, len, ".")) { - ; - } else if (!path.compare(beg, len, "..")) { - if (level == 0) { return false; } - level--; - } else { - level++; - } - - // Skip slash - while (i < path.size() && path[i] == '/') { - i++; - } - } - - return true; -} - -inline std::string encode_query_param(const std::string &value) { - std::ostringstream escaped; - escaped.fill('0'); - escaped << std::hex; - - for (auto c : value) { - if (std::isalnum(static_cast(c)) || c == '-' || c == '_' || - c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' || - c == ')') { - escaped << c; - } else { - escaped << std::uppercase; - escaped << '%' << std::setw(2) - << static_cast(static_cast(c)); - escaped << std::nouppercase; - } - } - - return escaped.str(); -} - -inline std::string encode_url(const std::string &s) { - std::string result; - result.reserve(s.size()); - - for (size_t i = 0; s[i]; i++) { - switch (s[i]) { - case ' ': result += "%20"; break; - case '+': result += "%2B"; break; - case '\r': result += "%0D"; break; - case '\n': result += "%0A"; break; - case '\'': result += "%27"; break; - case ',': result += "%2C"; break; - // case ':': result += "%3A"; break; // ok? probably... - case ';': result += "%3B"; break; - default: - auto c = static_cast(s[i]); - if (c >= 0x80) { - result += '%'; - char hex[4]; - auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c); - assert(len == 2); - result.append(hex, static_cast(len)); - } else { - result += s[i]; - } - break; - } - } - - return result; -} - -inline std::string decode_url(const std::string &s, - bool convert_plus_to_space) { - std::string result; - - for (size_t i = 0; i < s.size(); i++) { - if (s[i] == '%' && i + 1 < s.size()) { - if (s[i + 1] == 'u') { - int val = 0; - if (from_hex_to_i(s, i + 2, 4, val)) { - // 4 digits Unicode codes - char buff[4]; - size_t len = to_utf8(val, buff); - if (len > 0) { result.append(buff, len); } - i += 5; // 'u0000' - } else { - result += s[i]; - } - } else { - int val = 0; - if (from_hex_to_i(s, i + 1, 2, val)) { - // 2 digits hex codes - result += static_cast(val); - i += 2; // '00' - } else { - result += s[i]; - } - } - } else if (convert_plus_to_space && s[i] == '+') { - result += ' '; - } else { - result += s[i]; - } - } - - return result; -} - -inline void read_file(const std::string &path, std::string &out) { - std::ifstream fs(path, std::ios_base::binary); - fs.seekg(0, std::ios_base::end); - auto size = fs.tellg(); - fs.seekg(0); - out.resize(static_cast(size)); - fs.read(&out[0], static_cast(size)); -} - -inline std::string file_extension(const std::string &path) { - std::smatch m; - static auto re = std::regex("\\.([a-zA-Z0-9]+)$"); - if (std::regex_search(path, m, re)) { return m[1].str(); } - return std::string(); -} - -inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; } - -inline std::pair trim(const char *b, const char *e, size_t left, - size_t right) { - while (b + left < e && is_space_or_tab(b[left])) { - left++; - } - while (right > 0 && is_space_or_tab(b[right - 1])) { - right--; - } - return std::make_pair(left, right); -} - -inline std::string trim_copy(const std::string &s) { - auto r = trim(s.data(), s.data() + s.size(), 0, s.size()); - return s.substr(r.first, r.second - r.first); -} - -inline void split(const char *b, const char *e, char d, - std::function fn) { - size_t i = 0; - size_t beg = 0; - - while (e ? (b + i < e) : (b[i] != '\0')) { - if (b[i] == d) { - auto r = trim(b, e, beg, i); - if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } - beg = i + 1; - } - i++; - } - - if (i) { - auto r = trim(b, e, beg, i); - if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } - } -} - -inline stream_line_reader::stream_line_reader(Stream &strm, char *fixed_buffer, - size_t fixed_buffer_size) - : strm_(strm), fixed_buffer_(fixed_buffer), - fixed_buffer_size_(fixed_buffer_size) {} - -inline const char *stream_line_reader::ptr() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_; - } else { - return glowable_buffer_.data(); - } -} - -inline size_t stream_line_reader::size() const { - if (glowable_buffer_.empty()) { - return fixed_buffer_used_size_; - } else { - return glowable_buffer_.size(); - } -} - -inline bool stream_line_reader::end_with_crlf() const { - auto end = ptr() + size(); - return size() >= 2 && end[-2] == '\r' && end[-1] == '\n'; -} - -inline bool stream_line_reader::getline() { - fixed_buffer_used_size_ = 0; - glowable_buffer_.clear(); - - for (size_t i = 0;; i++) { - char byte; - auto n = strm_.read(&byte, 1); - - if (n < 0) { - return false; - } else if (n == 0) { - if (i == 0) { - return false; - } else { - break; - } - } - - append(byte); - - if (byte == '\n') { break; } - } - - return true; -} - -inline void stream_line_reader::append(char c) { - if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) { - fixed_buffer_[fixed_buffer_used_size_++] = c; - fixed_buffer_[fixed_buffer_used_size_] = '\0'; - } else { - if (glowable_buffer_.empty()) { - assert(fixed_buffer_[fixed_buffer_used_size_] == '\0'); - glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_); - } - glowable_buffer_ += c; - } -} - -inline int close_socket(socket_t sock) { -#ifdef _WIN32 - return closesocket(sock); -#else - return close(sock); -#endif -} - -template inline ssize_t handle_EINTR(T fn) { - ssize_t res = false; - while (true) { - res = fn(); - if (res < 0 && errno == EINTR) { continue; } - break; - } - return res; -} - -inline ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags) { - return handle_EINTR([&]() { - return recv(sock, -#ifdef _WIN32 - static_cast(ptr), static_cast(size), -#else - ptr, size, -#endif - flags); - }); -} - -inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size, - int flags) { - return handle_EINTR([&]() { - return send(sock, -#ifdef _WIN32 - static_cast(ptr), static_cast(size), -#else - ptr, size, -#endif - flags); - }); -} - -inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLIN; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return 1; } -#endif - - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - return handle_EINTR([&]() { - return select(static_cast(sock + 1), &fds, nullptr, nullptr, &tv); - }); -#endif -} - -inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLOUT; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return 1; } -#endif - - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - return handle_EINTR([&]() { - return select(static_cast(sock + 1), nullptr, &fds, nullptr, &tv); - }); -#endif -} - -inline Error wait_until_socket_is_ready(socket_t sock, time_t sec, - time_t usec) { -#ifdef CPPHTTPLIB_USE_POLL - struct pollfd pfd_read; - pfd_read.fd = sock; - pfd_read.events = POLLIN | POLLOUT; - - auto timeout = static_cast(sec * 1000 + usec / 1000); - - auto poll_res = handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); - - if (poll_res == 0) { return Error::ConnectionTimeout; } - - if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) { - int error = 0; - socklen_t len = sizeof(error); - auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, - reinterpret_cast(&error), &len); - auto successful = res >= 0 && !error; - return successful ? Error::Success : Error::Connection; - } - - return Error::Connection; -#else -#ifndef _WIN32 - if (sock >= FD_SETSIZE) { return Error::Connection; } -#endif - - fd_set fdsr; - FD_ZERO(&fdsr); - FD_SET(sock, &fdsr); - - auto fdsw = fdsr; - auto fdse = fdsr; - - timeval tv; - tv.tv_sec = static_cast(sec); - tv.tv_usec = static_cast(usec); - - auto ret = handle_EINTR([&]() { - return select(static_cast(sock + 1), &fdsr, &fdsw, &fdse, &tv); - }); - - if (ret == 0) { return Error::ConnectionTimeout; } - - if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) { - int error = 0; - socklen_t len = sizeof(error); - auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, - reinterpret_cast(&error), &len); - auto successful = res >= 0 && !error; - return successful ? Error::Success : Error::Connection; - } - return Error::Connection; -#endif -} - -inline bool is_socket_alive(socket_t sock) { - const auto val = detail::select_read(sock, 0, 0); - if (val == 0) { - return true; - } else if (val < 0 && errno == EBADF) { - return false; - } - char buf[1]; - return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0; -} - -class SocketStream : public Stream { -public: - SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, - time_t write_timeout_sec, time_t write_timeout_usec); - ~SocketStream() override; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - -private: - socket_t sock_; - time_t read_timeout_sec_; - time_t read_timeout_usec_; - time_t write_timeout_sec_; - time_t write_timeout_usec_; - - std::vector read_buff_; - size_t read_buff_off_ = 0; - size_t read_buff_content_size_ = 0; - - static const size_t read_buff_size_ = 1024 * 4; -}; - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -class SSLSocketStream : public Stream { -public: - SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec); - ~SSLSocketStream() override; - - bool is_readable() const override; - bool is_writable() const override; - ssize_t read(char *ptr, size_t size) override; - ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; - void get_local_ip_and_port(std::string &ip, int &port) const override; - socket_t socket() const override; - -private: - socket_t sock_; - SSL *ssl_; - time_t read_timeout_sec_; - time_t read_timeout_usec_; - time_t write_timeout_sec_; - time_t write_timeout_usec_; -}; -#endif - -inline bool keep_alive(socket_t sock, time_t keep_alive_timeout_sec) { - using namespace std::chrono; - auto start = steady_clock::now(); - while (true) { - auto val = select_read(sock, 0, 10000); - if (val < 0) { - return false; - } else if (val == 0) { - auto current = steady_clock::now(); - auto duration = duration_cast(current - start); - auto timeout = keep_alive_timeout_sec * 1000; - if (duration.count() > timeout) { return false; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } else { - return true; - } - } -} - -template -inline bool -process_server_socket_core(const std::atomic &svr_sock, socket_t sock, - size_t keep_alive_max_count, - time_t keep_alive_timeout_sec, T callback) { - assert(keep_alive_max_count > 0); - auto ret = false; - auto count = keep_alive_max_count; - while (svr_sock != INVALID_SOCKET && count > 0 && - keep_alive(sock, keep_alive_timeout_sec)) { - auto close_connection = count == 1; - auto connection_closed = false; - ret = callback(close_connection, connection_closed); - if (!ret || connection_closed) { break; } - count--; - } - return ret; -} - -template -inline bool -process_server_socket(const std::atomic &svr_sock, socket_t sock, - size_t keep_alive_max_count, - time_t keep_alive_timeout_sec, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - return process_server_socket_core( - svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, - [&](bool close_connection, bool &connection_closed) { - SocketStream strm(sock, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm, close_connection, connection_closed); - }); -} - -inline bool process_client_socket(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec, - std::function callback) { - SocketStream strm(sock, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm); -} - -inline int shutdown_socket(socket_t sock) { -#ifdef _WIN32 - return shutdown(sock, SD_BOTH); -#else - return shutdown(sock, SHUT_RDWR); -#endif -} - -template -socket_t create_socket(const std::string &host, const std::string &ip, int port, - int address_family, int socket_flags, bool tcp_nodelay, - SocketOptions socket_options, - BindOrConnect bind_or_connect) { - // Get address info - const char *node = nullptr; - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (!ip.empty()) { - node = ip.c_str(); - // Ask getaddrinfo to convert IP in c-string to address - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - } else { - if (!host.empty()) { node = host.c_str(); } - hints.ai_family = address_family; - hints.ai_flags = socket_flags; - } - -#ifndef _WIN32 - if (hints.ai_family == AF_UNIX) { - const auto addrlen = host.length(); - if (addrlen > sizeof(sockaddr_un::sun_path)) return INVALID_SOCKET; - - auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); - if (sock != INVALID_SOCKET) { - sockaddr_un addr{}; - addr.sun_family = AF_UNIX; - std::copy(host.begin(), host.end(), addr.sun_path); - - hints.ai_addr = reinterpret_cast(&addr); - hints.ai_addrlen = static_cast( - sizeof(addr) - sizeof(addr.sun_path) + addrlen); - - fcntl(sock, F_SETFD, FD_CLOEXEC); - if (socket_options) { socket_options(sock); } - - if (!bind_or_connect(sock, hints)) { - close_socket(sock); - sock = INVALID_SOCKET; - } - } - return sock; - } -#endif - - auto service = std::to_string(port); - - if (getaddrinfo(node, service.c_str(), &hints, &result)) { -#if defined __linux__ && !defined __ANDROID__ - res_init(); -#endif - return INVALID_SOCKET; - } - - for (auto rp = result; rp; rp = rp->ai_next) { - // Create a socket -#ifdef _WIN32 - auto sock = - WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, nullptr, 0, - WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); - /** - * Since the WSA_FLAG_NO_HANDLE_INHERIT is only supported on Windows 7 SP1 - * and above the socket creation fails on older Windows Systems. - * - * Let's try to create a socket the old way in this case. - * - * Reference: - * https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa - * - * WSA_FLAG_NO_HANDLE_INHERIT: - * This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with - * SP1, and later - * - */ - if (sock == INVALID_SOCKET) { - sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - } -#else - auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); -#endif - if (sock == INVALID_SOCKET) { continue; } - -#ifndef _WIN32 - if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { - close_socket(sock); - continue; - } -#endif - - if (tcp_nodelay) { - int yes = 1; - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&yes), - sizeof(yes)); - } - - if (socket_options) { socket_options(sock); } - - if (rp->ai_family == AF_INET6) { - int no = 0; - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&no), - sizeof(no)); - } - - // bind or connect - if (bind_or_connect(sock, *rp)) { - freeaddrinfo(result); - return sock; - } - - close_socket(sock); - } - - freeaddrinfo(result); - return INVALID_SOCKET; -} - -inline void set_nonblocking(socket_t sock, bool nonblocking) { -#ifdef _WIN32 - auto flags = nonblocking ? 1UL : 0UL; - ioctlsocket(sock, FIONBIO, &flags); -#else - auto flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, - nonblocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK))); -#endif -} - -inline bool is_connection_error() { -#ifdef _WIN32 - return WSAGetLastError() != WSAEWOULDBLOCK; -#else - return errno != EINPROGRESS; -#endif -} - -inline bool bind_ip_address(socket_t sock, const std::string &host) { - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(host.c_str(), "0", &hints, &result)) { return false; } - - auto ret = false; - for (auto rp = result; rp; rp = rp->ai_next) { - const auto &ai = *rp; - if (!::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { - ret = true; - break; - } - } - - freeaddrinfo(result); - return ret; -} - -#if !defined _WIN32 && !defined ANDROID && !defined _AIX -#define USE_IF2IP -#endif - -#ifdef USE_IF2IP -inline std::string if2ip(int address_family, const std::string &ifn) { - struct ifaddrs *ifap; - getifaddrs(&ifap); - std::string addr_candidate; - for (auto ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr && ifn == ifa->ifa_name && - (AF_UNSPEC == address_family || - ifa->ifa_addr->sa_family == address_family)) { - if (ifa->ifa_addr->sa_family == AF_INET) { - auto sa = reinterpret_cast(ifa->ifa_addr); - char buf[INET_ADDRSTRLEN]; - if (inet_ntop(AF_INET, &sa->sin_addr, buf, INET_ADDRSTRLEN)) { - freeifaddrs(ifap); - return std::string(buf, INET_ADDRSTRLEN); - } - } else if (ifa->ifa_addr->sa_family == AF_INET6) { - auto sa = reinterpret_cast(ifa->ifa_addr); - if (!IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) { - char buf[INET6_ADDRSTRLEN] = {}; - if (inet_ntop(AF_INET6, &sa->sin6_addr, buf, INET6_ADDRSTRLEN)) { - // equivalent to mac's IN6_IS_ADDR_UNIQUE_LOCAL - auto s6_addr_head = sa->sin6_addr.s6_addr[0]; - if (s6_addr_head == 0xfc || s6_addr_head == 0xfd) { - addr_candidate = std::string(buf, INET6_ADDRSTRLEN); - } else { - freeifaddrs(ifap); - return std::string(buf, INET6_ADDRSTRLEN); - } - } - } - } - } - } - freeifaddrs(ifap); - return addr_candidate; -} -#endif - -inline socket_t create_client_socket( - const std::string &host, const std::string &ip, int port, - int address_family, bool tcp_nodelay, SocketOptions socket_options, - time_t connection_timeout_sec, time_t connection_timeout_usec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, const std::string &intf, Error &error) { - auto sock = create_socket( - host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), - [&](socket_t sock2, struct addrinfo &ai) -> bool { - if (!intf.empty()) { -#ifdef USE_IF2IP - auto ip_from_if = if2ip(address_family, intf); - if (ip_from_if.empty()) { ip_from_if = intf; } - if (!bind_ip_address(sock2, ip_from_if.c_str())) { - error = Error::BindIPAddress; - return false; - } -#endif - } - - set_nonblocking(sock2, true); - - auto ret = - ::connect(sock2, ai.ai_addr, static_cast(ai.ai_addrlen)); - - if (ret < 0) { - if (is_connection_error()) { - error = Error::Connection; - return false; - } - error = wait_until_socket_is_ready(sock2, connection_timeout_sec, - connection_timeout_usec); - if (error != Error::Success) { return false; } - } - - set_nonblocking(sock2, false); - - { -#ifdef _WIN32 - auto timeout = static_cast(read_timeout_sec * 1000 + - read_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(read_timeout_sec); - tv.tv_usec = static_cast(read_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); -#endif - } - { - -#ifdef _WIN32 - auto timeout = static_cast(write_timeout_sec * 1000 + - write_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, - sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(write_timeout_sec); - tv.tv_usec = static_cast(write_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); -#endif - } - - error = Error::Success; - return true; - }); - - if (sock != INVALID_SOCKET) { - error = Error::Success; - } else { - if (error == Error::Success) { error = Error::Connection; } - } - - return sock; -} - -inline bool get_ip_and_port(const struct sockaddr_storage &addr, - socklen_t addr_len, std::string &ip, int &port) { - if (addr.ss_family == AF_INET) { - port = ntohs(reinterpret_cast(&addr)->sin_port); - } else if (addr.ss_family == AF_INET6) { - port = - ntohs(reinterpret_cast(&addr)->sin6_port); - } else { - return false; - } - - std::array ipstr{}; - if (getnameinfo(reinterpret_cast(&addr), addr_len, - ipstr.data(), static_cast(ipstr.size()), nullptr, - 0, NI_NUMERICHOST)) { - return false; - } - - ip = ipstr.data(); - return true; -} - -inline void get_local_ip_and_port(socket_t sock, std::string &ip, int &port) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - if (!getsockname(sock, reinterpret_cast(&addr), - &addr_len)) { - get_ip_and_port(addr, addr_len, ip, port); - } -} - -inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - - if (!getpeername(sock, reinterpret_cast(&addr), - &addr_len)) { -#ifndef _WIN32 - if (addr.ss_family == AF_UNIX) { -#if defined(__linux__) - struct ucred ucred; - socklen_t len = sizeof(ucred); - if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) { - port = ucred.pid; - } -#elif defined(SOL_LOCAL) && defined(SO_PEERPID) // __APPLE__ - pid_t pid; - socklen_t len = sizeof(pid); - if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) { - port = pid; - } -#endif - return; - } -#endif - get_ip_and_port(addr, addr_len, ip, port); - } -} - -inline constexpr unsigned int str2tag_core(const char *s, size_t l, - unsigned int h) { - return (l == 0) - ? h - : str2tag_core( - s + 1, l - 1, - // Unsets the 6 high bits of h, therefore no overflow happens - (((std::numeric_limits::max)() >> 6) & - h * 33) ^ - static_cast(*s)); -} - -inline unsigned int str2tag(const std::string &s) { - return str2tag_core(s.data(), s.size(), 0); -} - -namespace udl { - -inline constexpr unsigned int operator"" _t(const char *s, size_t l) { - return str2tag_core(s, l, 0); -} - -} // namespace udl - -inline const char * -find_content_type(const std::string &path, - const std::map &user_data) { - auto ext = file_extension(path); - - auto it = user_data.find(ext); - if (it != user_data.end()) { return it->second.c_str(); } - - using udl::operator""_t; - - switch (str2tag(ext)) { - default: return nullptr; - case "css"_t: return "text/css"; - case "csv"_t: return "text/csv"; - case "htm"_t: - case "html"_t: return "text/html"; - case "js"_t: - case "mjs"_t: return "text/javascript"; - case "txt"_t: return "text/plain"; - case "vtt"_t: return "text/vtt"; - - case "apng"_t: return "image/apng"; - case "avif"_t: return "image/avif"; - case "bmp"_t: return "image/bmp"; - case "gif"_t: return "image/gif"; - case "png"_t: return "image/png"; - case "svg"_t: return "image/svg+xml"; - case "webp"_t: return "image/webp"; - case "ico"_t: return "image/x-icon"; - case "tif"_t: return "image/tiff"; - case "tiff"_t: return "image/tiff"; - case "jpg"_t: - case "jpeg"_t: return "image/jpeg"; - - case "mp4"_t: return "video/mp4"; - case "mpeg"_t: return "video/mpeg"; - case "webm"_t: return "video/webm"; - - case "mp3"_t: return "audio/mp3"; - case "mpga"_t: return "audio/mpeg"; - case "weba"_t: return "audio/webm"; - case "wav"_t: return "audio/wave"; - - case "otf"_t: return "font/otf"; - case "ttf"_t: return "font/ttf"; - case "woff"_t: return "font/woff"; - case "woff2"_t: return "font/woff2"; - - case "7z"_t: return "application/x-7z-compressed"; - case "atom"_t: return "application/atom+xml"; - case "pdf"_t: return "application/pdf"; - case "json"_t: return "application/json"; - case "rss"_t: return "application/rss+xml"; - case "tar"_t: return "application/x-tar"; - case "xht"_t: - case "xhtml"_t: return "application/xhtml+xml"; - case "xslt"_t: return "application/xslt+xml"; - case "xml"_t: return "application/xml"; - case "gz"_t: return "application/gzip"; - case "zip"_t: return "application/zip"; - case "wasm"_t: return "application/wasm"; - } -} - -inline const char *status_message(int status) { - switch (status) { - case 100: return "Continue"; - case 101: return "Switching Protocol"; - case 102: return "Processing"; - case 103: return "Early Hints"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 208: return "Already Reported"; - case 226: return "IM Used"; - case 300: return "Multiple Choice"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 306: return "unused"; - case 307: return "Temporary Redirect"; - case 308: return "Permanent Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Payload Too Large"; - case 414: return "URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 418: return "I'm a teapot"; - case 421: return "Misdirected Request"; - case 422: return "Unprocessable Entity"; - case 423: return "Locked"; - case 424: return "Failed Dependency"; - case 425: return "Too Early"; - case 426: return "Upgrade Required"; - case 428: return "Precondition Required"; - case 429: return "Too Many Requests"; - case 431: return "Request Header Fields Too Large"; - case 451: return "Unavailable For Legal Reasons"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "HTTP Version Not Supported"; - case 506: return "Variant Also Negotiates"; - case 507: return "Insufficient Storage"; - case 508: return "Loop Detected"; - case 510: return "Not Extended"; - case 511: return "Network Authentication Required"; - - default: - case 500: return "Internal Server Error"; - } -} - -inline bool can_compress_content_type(const std::string &content_type) { - using udl::operator""_t; - - auto tag = str2tag(content_type); - - switch (tag) { - case "image/svg+xml"_t: - case "application/javascript"_t: - case "application/json"_t: - case "application/xml"_t: - case "application/protobuf"_t: - case "application/xhtml+xml"_t: return true; - - default: - return !content_type.rfind("text/", 0) && tag != "text/event-stream"_t; - } -} - -inline EncodingType encoding_type(const Request &req, const Response &res) { - auto ret = - detail::can_compress_content_type(res.get_header_value("Content-Type")); - if (!ret) { return EncodingType::None; } - - const auto &s = req.get_header_value("Accept-Encoding"); - (void)(s); - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - // TODO: 'Accept-Encoding' has br, not br;q=0 - ret = s.find("br") != std::string::npos; - if (ret) { return EncodingType::Brotli; } -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - // TODO: 'Accept-Encoding' has gzip, not gzip;q=0 - ret = s.find("gzip") != std::string::npos; - if (ret) { return EncodingType::Gzip; } -#endif - - return EncodingType::None; -} - -inline bool nocompressor::compress(const char *data, size_t data_length, - bool /*last*/, Callback callback) { - if (!data_length) { return true; } - return callback(data, data_length); -} - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT -inline gzip_compressor::gzip_compressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; - - is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, - Z_DEFAULT_STRATEGY) == Z_OK; -} - -inline gzip_compressor::~gzip_compressor() { deflateEnd(&strm_); } - -inline bool gzip_compressor::compress(const char *data, size_t data_length, - bool last, Callback callback) { - assert(is_valid_); - - do { - constexpr size_t max_avail_in = - (std::numeric_limits::max)(); - - strm_.avail_in = static_cast( - (std::min)(data_length, max_avail_in)); - strm_.next_in = const_cast(reinterpret_cast(data)); - - data_length -= strm_.avail_in; - data += strm_.avail_in; - - auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH; - int ret = Z_OK; - - std::array buff{}; - do { - strm_.avail_out = static_cast(buff.size()); - strm_.next_out = reinterpret_cast(buff.data()); - - ret = deflate(&strm_, flush); - if (ret == Z_STREAM_ERROR) { return false; } - - if (!callback(buff.data(), buff.size() - strm_.avail_out)) { - return false; - } - } while (strm_.avail_out == 0); - - assert((flush == Z_FINISH && ret == Z_STREAM_END) || - (flush == Z_NO_FLUSH && ret == Z_OK)); - assert(strm_.avail_in == 0); - } while (data_length > 0); - - return true; -} - -inline gzip_decompressor::gzip_decompressor() { - std::memset(&strm_, 0, sizeof(strm_)); - strm_.zalloc = Z_NULL; - strm_.zfree = Z_NULL; - strm_.opaque = Z_NULL; - - // 15 is the value of wbits, which should be at the maximum possible value - // to ensure that any gzip stream can be decoded. The offset of 32 specifies - // that the stream type should be automatically detected either gzip or - // deflate. - is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK; -} - -inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); } - -inline bool gzip_decompressor::is_valid() const { return is_valid_; } - -inline bool gzip_decompressor::decompress(const char *data, size_t data_length, - Callback callback) { - assert(is_valid_); - - int ret = Z_OK; - - do { - constexpr size_t max_avail_in = - (std::numeric_limits::max)(); - - strm_.avail_in = static_cast( - (std::min)(data_length, max_avail_in)); - strm_.next_in = const_cast(reinterpret_cast(data)); - - data_length -= strm_.avail_in; - data += strm_.avail_in; - - std::array buff{}; - while (strm_.avail_in > 0) { - strm_.avail_out = static_cast(buff.size()); - strm_.next_out = reinterpret_cast(buff.data()); - - auto prev_avail_in = strm_.avail_in; - - ret = inflate(&strm_, Z_NO_FLUSH); - - if (prev_avail_in - strm_.avail_in == 0) { return false; } - - assert(ret != Z_STREAM_ERROR); - switch (ret) { - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_MEM_ERROR: inflateEnd(&strm_); return false; - } - - if (!callback(buff.data(), buff.size() - strm_.avail_out)) { - return false; - } - } - - if (ret != Z_OK && ret != Z_STREAM_END) return false; - - } while (data_length > 0); - - return true; -} -#endif - -#ifdef CPPHTTPLIB_BROTLI_SUPPORT -inline brotli_compressor::brotli_compressor() { - state_ = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); -} - -inline brotli_compressor::~brotli_compressor() { - BrotliEncoderDestroyInstance(state_); -} - -inline bool brotli_compressor::compress(const char *data, size_t data_length, - bool last, Callback callback) { - std::array buff{}; - - auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS; - auto available_in = data_length; - auto next_in = reinterpret_cast(data); - - for (;;) { - if (last) { - if (BrotliEncoderIsFinished(state_)) { break; } - } else { - if (!available_in) { break; } - } - - auto available_out = buff.size(); - auto next_out = buff.data(); - - if (!BrotliEncoderCompressStream(state_, operation, &available_in, &next_in, - &available_out, &next_out, nullptr)) { - return false; - } - - auto output_bytes = buff.size() - available_out; - if (output_bytes) { - callback(reinterpret_cast(buff.data()), output_bytes); - } - } - - return true; -} - -inline brotli_decompressor::brotli_decompressor() { - decoder_s = BrotliDecoderCreateInstance(0, 0, 0); - decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT - : BROTLI_DECODER_RESULT_ERROR; -} - -inline brotli_decompressor::~brotli_decompressor() { - if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); } -} - -inline bool brotli_decompressor::is_valid() const { return decoder_s; } - -inline bool brotli_decompressor::decompress(const char *data, - size_t data_length, - Callback callback) { - if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_ERROR) { - return 0; - } - - const uint8_t *next_in = (const uint8_t *)data; - size_t avail_in = data_length; - size_t total_out; - - decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; - - std::array buff{}; - while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { - char *next_out = buff.data(); - size_t avail_out = buff.size(); - - decoder_r = BrotliDecoderDecompressStream( - decoder_s, &avail_in, &next_in, &avail_out, - reinterpret_cast(&next_out), &total_out); - - if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false; } - - if (!callback(buff.data(), buff.size() - avail_out)) { return false; } - } - - return decoder_r == BROTLI_DECODER_RESULT_SUCCESS || - decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; -} -#endif - -inline bool has_header(const Headers &headers, const std::string &key) { - return headers.find(key) != headers.end(); -} - -inline const char *get_header_value(const Headers &headers, - const std::string &key, size_t id, - const char *def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { return it->second.c_str(); } - return def; -} - -inline bool compare_case_ignore(const std::string &a, const std::string &b) { - if (a.size() != b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (::tolower(a[i]) != ::tolower(b[i])) { return false; } - } - return true; -} - -template -inline bool parse_header(const char *beg, const char *end, T fn) { - // Skip trailing spaces and tabs. - while (beg < end && is_space_or_tab(end[-1])) { - end--; - } - - auto p = beg; - while (p < end && *p != ':') { - p++; - } - - if (p == end) { return false; } - - auto key_end = p; - - if (*p++ != ':') { return false; } - - while (p < end && is_space_or_tab(*p)) { - p++; - } - - if (p < end) { - auto key = std::string(beg, key_end); - auto val = compare_case_ignore(key, "Location") - ? std::string(p, end) - : decode_url(std::string(p, end), false); - fn(std::move(key), std::move(val)); - return true; - } - - return false; -} - -inline bool read_headers(Stream &strm, Headers &headers) { - const auto bufsiz = 2048; - char buf[bufsiz]; - stream_line_reader line_reader(strm, buf, bufsiz); - - for (;;) { - if (!line_reader.getline()) { return false; } - - // Check if the line ends with CRLF. - auto line_terminator_len = 2; - if (line_reader.end_with_crlf()) { - // Blank line indicates end of headers. - if (line_reader.size() == 2) { break; } -#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR - } else { - // Blank line indicates end of headers. - if (line_reader.size() == 1) { break; } - line_terminator_len = 1; - } -#else - } else { - continue; // Skip invalid line. - } -#endif - - if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - - // Exclude line terminator - auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; - - parse_header(line_reader.ptr(), end, - [&](std::string &&key, std::string &&val) { - headers.emplace(std::move(key), std::move(val)); - }); - } - - return true; -} - -inline bool read_content_with_length(Stream &strm, uint64_t len, - Progress progress, - ContentReceiverWithProgress out) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - - uint64_t r = 0; - while (r < len) { - auto read_len = static_cast(len - r); - auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ)); - if (n <= 0) { return false; } - - if (!out(buf, static_cast(n), r, len)) { return false; } - r += static_cast(n); - - if (progress) { - if (!progress(r, len)) { return false; } - } - } - - return true; -} - -inline void skip_content_with_length(Stream &strm, uint64_t len) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - uint64_t r = 0; - while (r < len) { - auto read_len = static_cast(len - r); - auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ)); - if (n <= 0) { return; } - r += static_cast(n); - } -} - -inline bool read_content_without_length(Stream &strm, - ContentReceiverWithProgress out) { - char buf[CPPHTTPLIB_RECV_BUFSIZ]; - uint64_t r = 0; - for (;;) { - auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ); - if (n < 0) { - return false; - } else if (n == 0) { - return true; - } - - if (!out(buf, static_cast(n), r, 0)) { return false; } - r += static_cast(n); - } - - return true; -} - -template -inline bool read_content_chunked(Stream &strm, T &x, - ContentReceiverWithProgress out) { - const auto bufsiz = 16; - char buf[bufsiz]; - - stream_line_reader line_reader(strm, buf, bufsiz); - - if (!line_reader.getline()) { return false; } - - unsigned long chunk_len; - while (true) { - char *end_ptr; - - chunk_len = std::strtoul(line_reader.ptr(), &end_ptr, 16); - - if (end_ptr == line_reader.ptr()) { return false; } - if (chunk_len == ULONG_MAX) { return false; } - - if (chunk_len == 0) { break; } - - if (!read_content_with_length(strm, chunk_len, nullptr, out)) { - return false; - } - - if (!line_reader.getline()) { return false; } - - if (strcmp(line_reader.ptr(), "\r\n")) { return false; } - - if (!line_reader.getline()) { return false; } - } - - assert(chunk_len == 0); - - // Trailer - if (!line_reader.getline()) { return false; } - - while (strcmp(line_reader.ptr(), "\r\n")) { - if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - - // Exclude line terminator - constexpr auto line_terminator_len = 2; - auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; - - parse_header(line_reader.ptr(), end, - [&](std::string &&key, std::string &&val) { - x.headers.emplace(std::move(key), std::move(val)); - }); - - if (!line_reader.getline()) { return false; } - } - - return true; -} - -inline bool is_chunked_transfer_encoding(const Headers &headers) { - return !strcasecmp(get_header_value(headers, "Transfer-Encoding", 0, ""), - "chunked"); -} - -template -bool prepare_content_receiver(T &x, int &status, - ContentReceiverWithProgress receiver, - bool decompress, U callback) { - if (decompress) { - std::string encoding = x.get_header_value("Content-Encoding"); - std::unique_ptr decompressor; - - if (encoding == "gzip" || encoding == "deflate") { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - decompressor = detail::make_unique(); -#else - status = 415; - return false; -#endif - } else if (encoding.find("br") != std::string::npos) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - decompressor = detail::make_unique(); -#else - status = 415; - return false; -#endif - } - - if (decompressor) { - if (decompressor->is_valid()) { - ContentReceiverWithProgress out = [&](const char *buf, size_t n, - uint64_t off, uint64_t len) { - return decompressor->decompress(buf, n, - [&](const char *buf2, size_t n2) { - return receiver(buf2, n2, off, len); - }); - }; - return callback(std::move(out)); - } else { - status = 500; - return false; - } - } - } - - ContentReceiverWithProgress out = [&](const char *buf, size_t n, uint64_t off, - uint64_t len) { - return receiver(buf, n, off, len); - }; - return callback(std::move(out)); -} - -template -bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status, - Progress progress, ContentReceiverWithProgress receiver, - bool decompress) { - return prepare_content_receiver( - x, status, std::move(receiver), decompress, - [&](const ContentReceiverWithProgress &out) { - auto ret = true; - auto exceed_payload_max_length = false; - - if (is_chunked_transfer_encoding(x.headers)) { - ret = read_content_chunked(strm, x, out); - } else if (!has_header(x.headers, "Content-Length")) { - ret = read_content_without_length(strm, out); - } else { - auto len = get_header_value(x.headers, "Content-Length"); - if (len > payload_max_length) { - exceed_payload_max_length = true; - skip_content_with_length(strm, len); - ret = false; - } else if (len > 0) { - ret = read_content_with_length(strm, len, std::move(progress), out); - } - } - - if (!ret) { status = exceed_payload_max_length ? 413 : 400; } - return ret; - }); -} // namespace detail - -inline ssize_t write_headers(Stream &strm, const Headers &headers) { - ssize_t write_len = 0; - for (const auto &x : headers) { - auto len = - strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str()); - if (len < 0) { return len; } - write_len += len; - } - auto len = strm.write("\r\n"); - if (len < 0) { return len; } - write_len += len; - return write_len; -} - -inline bool write_data(Stream &strm, const char *d, size_t l) { - size_t offset = 0; - while (offset < l) { - auto length = strm.write(d + offset, l - offset); - if (length < 0) { return false; } - offset += static_cast(length); - } - return true; -} - -template -inline bool write_content(Stream &strm, const ContentProvider &content_provider, - size_t offset, size_t length, T is_shutting_down, - Error &error) { - size_t end_offset = offset + length; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - if (strm.is_writable() && write_data(strm, d, l)) { - offset += l; - } else { - ok = false; - } - } - return ok; - }; - - while (offset < end_offset && !is_shutting_down()) { - if (!strm.is_writable()) { - error = Error::Write; - return false; - } else if (!content_provider(offset, end_offset - offset, data_sink)) { - error = Error::Canceled; - return false; - } else if (!ok) { - error = Error::Write; - return false; - } - } - - error = Error::Success; - return true; -} - -template -inline bool write_content(Stream &strm, const ContentProvider &content_provider, - size_t offset, size_t length, - const T &is_shutting_down) { - auto error = Error::Success; - return write_content(strm, content_provider, offset, length, is_shutting_down, - error); -} - -template -inline bool -write_content_without_length(Stream &strm, - const ContentProvider &content_provider, - const T &is_shutting_down) { - size_t offset = 0; - auto data_available = true; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - offset += l; - if (!strm.is_writable() || !write_data(strm, d, l)) { ok = false; } - } - return ok; - }; - - data_sink.done = [&](void) { data_available = false; }; - - while (data_available && !is_shutting_down()) { - if (!strm.is_writable()) { - return false; - } else if (!content_provider(offset, 0, data_sink)) { - return false; - } else if (!ok) { - return false; - } - } - return true; -} - -template -inline bool -write_content_chunked(Stream &strm, const ContentProvider &content_provider, - const T &is_shutting_down, U &compressor, Error &error) { - size_t offset = 0; - auto data_available = true; - auto ok = true; - DataSink data_sink; - - data_sink.write = [&](const char *d, size_t l) -> bool { - if (ok) { - data_available = l > 0; - offset += l; - - std::string payload; - if (compressor.compress(d, l, false, - [&](const char *data, size_t data_len) { - payload.append(data, data_len); - return true; - })) { - if (!payload.empty()) { - // Emit chunked response header and footer for each chunk - auto chunk = - from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!strm.is_writable() || - !write_data(strm, chunk.data(), chunk.size())) { - ok = false; - } - } - } else { - ok = false; - } - } - return ok; - }; - - auto done_with_trailer = [&](const Headers *trailer) { - if (!ok) { return; } - - data_available = false; - - std::string payload; - if (!compressor.compress(nullptr, 0, true, - [&](const char *data, size_t data_len) { - payload.append(data, data_len); - return true; - })) { - ok = false; - return; - } - - if (!payload.empty()) { - // Emit chunked response header and footer for each chunk - auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!strm.is_writable() || - !write_data(strm, chunk.data(), chunk.size())) { - ok = false; - return; - } - } - - static const std::string done_marker("0\r\n"); - if (!write_data(strm, done_marker.data(), done_marker.size())) { - ok = false; - } - - // Trailer - if (trailer) { - for (const auto &kv : *trailer) { - std::string field_line = kv.first + ": " + kv.second + "\r\n"; - if (!write_data(strm, field_line.data(), field_line.size())) { - ok = false; - } - } - } - - static const std::string crlf("\r\n"); - if (!write_data(strm, crlf.data(), crlf.size())) { ok = false; } - }; - - data_sink.done = [&](void) { done_with_trailer(nullptr); }; - - data_sink.done_with_trailer = [&](const Headers &trailer) { - done_with_trailer(&trailer); - }; - - while (data_available && !is_shutting_down()) { - if (!strm.is_writable()) { - error = Error::Write; - return false; - } else if (!content_provider(offset, 0, data_sink)) { - error = Error::Canceled; - return false; - } else if (!ok) { - error = Error::Write; - return false; - } - } - - error = Error::Success; - return true; -} - -template -inline bool write_content_chunked(Stream &strm, - const ContentProvider &content_provider, - const T &is_shutting_down, U &compressor) { - auto error = Error::Success; - return write_content_chunked(strm, content_provider, is_shutting_down, - compressor, error); -} - -template -inline bool redirect(T &cli, Request &req, Response &res, - const std::string &path, const std::string &location, - Error &error) { - Request new_req = req; - new_req.path = path; - new_req.redirect_count_ -= 1; - - if (res.status == 303 && (req.method != "GET" && req.method != "HEAD")) { - new_req.method = "GET"; - new_req.body.clear(); - new_req.headers.clear(); - } - - Response new_res; - - auto ret = cli.send(new_req, new_res, error); - if (ret) { - req = new_req; - res = new_res; - res.location = location; - } - return ret; -} - -inline std::string params_to_query_str(const Params ¶ms) { - std::string query; - - for (auto it = params.begin(); it != params.end(); ++it) { - if (it != params.begin()) { query += "&"; } - query += it->first; - query += "="; - query += encode_query_param(it->second); - } - return query; -} - -inline void parse_query_text(const std::string &s, Params ¶ms) { - std::set cache; - split(s.data(), s.data() + s.size(), '&', [&](const char *b, const char *e) { - std::string kv(b, e); - if (cache.find(kv) != cache.end()) { return; } - cache.insert(kv); - - std::string key; - std::string val; - split(b, e, '=', [&](const char *b2, const char *e2) { - if (key.empty()) { - key.assign(b2, e2); - } else { - val.assign(b2, e2); - } - }); - - if (!key.empty()) { - params.emplace(decode_url(key, true), decode_url(val, true)); - } - }); -} - -inline bool parse_multipart_boundary(const std::string &content_type, - std::string &boundary) { - auto boundary_keyword = "boundary="; - auto pos = content_type.find(boundary_keyword); - if (pos == std::string::npos) { return false; } - auto end = content_type.find(';', pos); - auto beg = pos + strlen(boundary_keyword); - boundary = content_type.substr(beg, end - beg); - if (boundary.length() >= 2 && boundary.front() == '"' && - boundary.back() == '"') { - boundary = boundary.substr(1, boundary.size() - 2); - } - return !boundary.empty(); -} - -#ifdef CPPHTTPLIB_NO_EXCEPTIONS -inline bool parse_range_header(const std::string &s, Ranges &ranges) { -#else -inline bool parse_range_header(const std::string &s, Ranges &ranges) try { -#endif - static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); - std::smatch m; - if (std::regex_match(s, m, re_first_range)) { - auto pos = static_cast(m.position(1)); - auto len = static_cast(m.length(1)); - bool all_valid_ranges = true; - split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) { - if (!all_valid_ranges) return; - static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))"); - std::cmatch cm; - if (std::regex_match(b, e, cm, re_another_range)) { - ssize_t first = -1; - if (!cm.str(1).empty()) { - first = static_cast(std::stoll(cm.str(1))); - } - - ssize_t last = -1; - if (!cm.str(2).empty()) { - last = static_cast(std::stoll(cm.str(2))); - } - - if (first != -1 && last != -1 && first > last) { - all_valid_ranges = false; - return; - } - ranges.emplace_back(std::make_pair(first, last)); - } - }); - return all_valid_ranges; - } - return false; -#ifdef CPPHTTPLIB_NO_EXCEPTIONS -} -#else -} catch (...) { return false; } -#endif - -class MultipartFormDataParser { -public: - MultipartFormDataParser() = default; - - void set_boundary(std::string &&boundary) { - boundary_ = boundary; - dash_boundary_crlf_ = dash_ + boundary_ + crlf_; - crlf_dash_boundary_ = crlf_ + dash_ + boundary_; - } - - bool is_valid() const { return is_valid_; } - - bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, - const MultipartContentHeader &header_callback) { - - // TODO: support 'filename*' - static const std::regex re_content_disposition( - R"~(^Content-Disposition:\s*form-data;\s*name="(.*?)"(?:;\s*filename="(.*?)")?(?:;\s*filename\*=\S+)?\s*$)~", - std::regex_constants::icase); - - buf_append(buf, n); - - while (buf_size() > 0) { - switch (state_) { - case 0: { // Initial boundary - buf_erase(buf_find(dash_boundary_crlf_)); - if (dash_boundary_crlf_.size() > buf_size()) { return true; } - if (!buf_start_with(dash_boundary_crlf_)) { return false; } - buf_erase(dash_boundary_crlf_.size()); - state_ = 1; - break; - } - case 1: { // New entry - clear_file_info(); - state_ = 2; - break; - } - case 2: { // Headers - auto pos = buf_find(crlf_); - if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - while (pos < buf_size()) { - // Empty line - if (pos == 0) { - if (!header_callback(file_)) { - is_valid_ = false; - return false; - } - buf_erase(crlf_.size()); - state_ = 3; - break; - } - - static const std::string header_name = "content-type:"; - const auto header = buf_head(pos); - if (start_with_case_ignore(header, header_name)) { - file_.content_type = trim_copy(header.substr(header_name.size())); - } else { - std::smatch m; - if (std::regex_match(header, m, re_content_disposition)) { - file_.name = m[1]; - file_.filename = m[2]; - } else { - is_valid_ = false; - return false; - } - } - buf_erase(pos + crlf_.size()); - pos = buf_find(crlf_); - } - if (state_ != 3) { return true; } - break; - } - case 3: { // Body - if (crlf_dash_boundary_.size() > buf_size()) { return true; } - auto pos = buf_find(crlf_dash_boundary_); - if (pos < buf_size()) { - if (!content_callback(buf_data(), pos)) { - is_valid_ = false; - return false; - } - buf_erase(pos + crlf_dash_boundary_.size()); - state_ = 4; - } else { - auto len = buf_size() - crlf_dash_boundary_.size(); - if (len > 0) { - if (!content_callback(buf_data(), len)) { - is_valid_ = false; - return false; - } - buf_erase(len); - } - return true; - } - break; - } - case 4: { // Boundary - if (crlf_.size() > buf_size()) { return true; } - if (buf_start_with(crlf_)) { - buf_erase(crlf_.size()); - state_ = 1; - } else { - if (dash_crlf_.size() > buf_size()) { return true; } - if (buf_start_with(dash_crlf_)) { - buf_erase(dash_crlf_.size()); - is_valid_ = true; - buf_erase(buf_size()); // Remove epilogue - } else { - return true; - } - } - break; - } - } - } - - return true; - } - -private: - void clear_file_info() { - file_.name.clear(); - file_.filename.clear(); - file_.content_type.clear(); - } - - bool start_with_case_ignore(const std::string &a, - const std::string &b) const { - if (a.size() < b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (::tolower(a[i]) != ::tolower(b[i])) { return false; } - } - return true; - } - - const std::string dash_ = "--"; - const std::string crlf_ = "\r\n"; - const std::string dash_crlf_ = "--\r\n"; - std::string boundary_; - std::string dash_boundary_crlf_; - std::string crlf_dash_boundary_; - - size_t state_ = 0; - bool is_valid_ = false; - MultipartFormData file_; - - // Buffer - bool start_with(const std::string &a, size_t spos, size_t epos, - const std::string &b) const { - if (epos - spos < b.size()) { return false; } - for (size_t i = 0; i < b.size(); i++) { - if (a[i + spos] != b[i]) { return false; } - } - return true; - } - - size_t buf_size() const { return buf_epos_ - buf_spos_; } - - const char *buf_data() const { return &buf_[buf_spos_]; } - - std::string buf_head(size_t l) const { return buf_.substr(buf_spos_, l); } - - bool buf_start_with(const std::string &s) const { - return start_with(buf_, buf_spos_, buf_epos_, s); - } - - size_t buf_find(const std::string &s) const { - auto c = s.front(); - - size_t off = buf_spos_; - while (off < buf_epos_) { - auto pos = off; - while (true) { - if (pos == buf_epos_) { return buf_size(); } - if (buf_[pos] == c) { break; } - pos++; - } - - auto remaining_size = buf_epos_ - pos; - if (s.size() > remaining_size) { return buf_size(); } - - if (start_with(buf_, pos, buf_epos_, s)) { return pos - buf_spos_; } - - off = pos + 1; - } - - return buf_size(); - } - - void buf_append(const char *data, size_t n) { - auto remaining_size = buf_size(); - if (remaining_size > 0 && buf_spos_ > 0) { - for (size_t i = 0; i < remaining_size; i++) { - buf_[i] = buf_[buf_spos_ + i]; - } - } - buf_spos_ = 0; - buf_epos_ = remaining_size; - - if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); } - - for (size_t i = 0; i < n; i++) { - buf_[buf_epos_ + i] = data[i]; - } - buf_epos_ += n; - } - - void buf_erase(size_t size) { buf_spos_ += size; } - - std::string buf_; - size_t buf_spos_ = 0; - size_t buf_epos_ = 0; -}; - -inline std::string to_lower(const char *beg, const char *end) { - std::string out; - auto it = beg; - while (it != end) { - out += static_cast(::tolower(*it)); - it++; - } - return out; -} - -inline std::string make_multipart_data_boundary() { - static const char data[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - // std::random_device might actually be deterministic on some - // platforms, but due to lack of support in the c++ standard library, - // doing better requires either some ugly hacks or breaking portability. - std::random_device seed_gen; - - // Request 128 bits of entropy for initialization - std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()}; - std::mt19937 engine(seed_sequence); - - std::string result = "--cpp-httplib-multipart-data-"; - - for (auto i = 0; i < 16; i++) { - result += data[engine() % (sizeof(data) - 1)]; - } - - return result; -} - -inline bool is_multipart_boundary_chars_valid(const std::string &boundary) { - auto valid = true; - for (size_t i = 0; i < boundary.size(); i++) { - auto c = boundary[i]; - if (!std::isalnum(c) && c != '-' && c != '_') { - valid = false; - break; - } - } - return valid; -} - -template -inline std::string -serialize_multipart_formdata_item_begin(const T &item, - const std::string &boundary) { - std::string body = "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + item.name + "\""; - if (!item.filename.empty()) { - body += "; filename=\"" + item.filename + "\""; - } - body += "\r\n"; - if (!item.content_type.empty()) { - body += "Content-Type: " + item.content_type + "\r\n"; - } - body += "\r\n"; - - return body; -} - -inline std::string serialize_multipart_formdata_item_end() { return "\r\n"; } - -inline std::string -serialize_multipart_formdata_finish(const std::string &boundary) { - return "--" + boundary + "--\r\n"; -} - -inline std::string -serialize_multipart_formdata_get_content_type(const std::string &boundary) { - return "multipart/form-data; boundary=" + boundary; -} - -inline std::string -serialize_multipart_formdata(const MultipartFormDataItems &items, - const std::string &boundary, bool finish = true) { - std::string body; - - for (const auto &item : items) { - body += serialize_multipart_formdata_item_begin(item, boundary); - body += item.content + serialize_multipart_formdata_item_end(); - } - - if (finish) body += serialize_multipart_formdata_finish(boundary); - - return body; -} - -inline std::pair -get_range_offset_and_length(const Request &req, size_t content_length, - size_t index) { - auto r = req.ranges[index]; - - if (r.first == -1 && r.second == -1) { - return std::make_pair(0, content_length); - } - - auto slen = static_cast(content_length); - - if (r.first == -1) { - r.first = (std::max)(static_cast(0), slen - r.second); - r.second = slen - 1; - } - - if (r.second == -1) { r.second = slen - 1; } - return std::make_pair(r.first, static_cast(r.second - r.first) + 1); -} - -inline std::string make_content_range_header_field(size_t offset, size_t length, - size_t content_length) { - std::string field = "bytes "; - field += std::to_string(offset); - field += "-"; - field += std::to_string(offset + length - 1); - field += "/"; - field += std::to_string(content_length); - return field; -} - -template -bool process_multipart_ranges_data(const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type, - SToken stoken, CToken ctoken, - Content content) { - for (size_t i = 0; i < req.ranges.size(); i++) { - ctoken("--"); - stoken(boundary); - ctoken("\r\n"); - if (!content_type.empty()) { - ctoken("Content-Type: "); - stoken(content_type); - ctoken("\r\n"); - } - - auto offsets = get_range_offset_and_length(req, res.body.size(), i); - auto offset = offsets.first; - auto length = offsets.second; - - ctoken("Content-Range: "); - stoken(make_content_range_header_field(offset, length, res.body.size())); - ctoken("\r\n"); - ctoken("\r\n"); - if (!content(offset, length)) { return false; } - ctoken("\r\n"); - } - - ctoken("--"); - stoken(boundary); - ctoken("--\r\n"); - - return true; -} - -inline bool make_multipart_ranges_data(const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type, - std::string &data) { - return process_multipart_ranges_data( - req, res, boundary, content_type, - [&](const std::string &token) { data += token; }, - [&](const std::string &token) { data += token; }, - [&](size_t offset, size_t length) { - if (offset < res.body.size()) { - data += res.body.substr(offset, length); - return true; - } - return false; - }); -} - -inline size_t -get_multipart_ranges_data_length(const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type) { - size_t data_length = 0; - - process_multipart_ranges_data( - req, res, boundary, content_type, - [&](const std::string &token) { data_length += token.size(); }, - [&](const std::string &token) { data_length += token.size(); }, - [&](size_t /*offset*/, size_t length) { - data_length += length; - return true; - }); - - return data_length; -} - -template -inline bool write_multipart_ranges_data(Stream &strm, const Request &req, - Response &res, - const std::string &boundary, - const std::string &content_type, - const T &is_shutting_down) { - return process_multipart_ranges_data( - req, res, boundary, content_type, - [&](const std::string &token) { strm.write(token); }, - [&](const std::string &token) { strm.write(token); }, - [&](size_t offset, size_t length) { - return write_content(strm, res.content_provider_, offset, length, - is_shutting_down); - }); -} - -inline std::pair -get_range_offset_and_length(const Request &req, const Response &res, - size_t index) { - auto r = req.ranges[index]; - - if (r.second == -1) { - r.second = static_cast(res.content_length_) - 1; - } - - return std::make_pair(r.first, r.second - r.first + 1); -} - -inline bool expect_content(const Request &req) { - if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" || - req.method == "PRI" || req.method == "DELETE") { - return true; - } - // TODO: check if Content-Length is set - return false; -} - -inline bool has_crlf(const std::string &s) { - auto p = s.c_str(); - while (*p) { - if (*p == '\r' || *p == '\n') { return true; } - p++; - } - return false; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline std::string message_digest(const std::string &s, const EVP_MD *algo) { - auto context = std::unique_ptr( - EVP_MD_CTX_new(), EVP_MD_CTX_free); - - unsigned int hash_length = 0; - unsigned char hash[EVP_MAX_MD_SIZE]; - - EVP_DigestInit_ex(context.get(), algo, nullptr); - EVP_DigestUpdate(context.get(), s.c_str(), s.size()); - EVP_DigestFinal_ex(context.get(), hash, &hash_length); - - std::stringstream ss; - for (auto i = 0u; i < hash_length; ++i) { - ss << std::hex << std::setw(2) << std::setfill('0') - << (unsigned int)hash[i]; - } - - return ss.str(); -} - -inline std::string MD5(const std::string &s) { - return message_digest(s, EVP_md5()); -} - -inline std::string SHA_256(const std::string &s) { - return message_digest(s, EVP_sha256()); -} - -inline std::string SHA_512(const std::string &s) { - return message_digest(s, EVP_sha512()); -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -#ifdef _WIN32 -// NOTE: This code came up with the following stackoverflow post: -// https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store -inline bool load_system_certs_on_windows(X509_STORE *store) { - auto hStore = CertOpenSystemStoreW((HCRYPTPROV_LEGACY)NULL, L"ROOT"); - if (!hStore) { return false; } - - auto result = false; - PCCERT_CONTEXT pContext = NULL; - while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != - nullptr) { - auto encoded_cert = - static_cast(pContext->pbCertEncoded); - - auto x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); - if (x509) { - X509_STORE_add_cert(store, x509); - X509_free(x509); - result = true; - } - } - - CertFreeCertificateContext(pContext); - CertCloseStore(hStore, 0); - - return result; -} -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#if TARGET_OS_OSX -template -using CFObjectPtr = - std::unique_ptr::type, void (*)(CFTypeRef)>; - -inline void cf_object_ptr_deleter(CFTypeRef obj) { - if (obj) { CFRelease(obj); } -} - -inline bool retrieve_certs_from_keychain(CFObjectPtr &certs) { - CFStringRef keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef}; - CFTypeRef values[] = {kSecClassCertificate, kSecMatchLimitAll, - kCFBooleanTrue}; - - CFObjectPtr query( - CFDictionaryCreate(nullptr, reinterpret_cast(keys), values, - sizeof(keys) / sizeof(keys[0]), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), - cf_object_ptr_deleter); - - if (!query) { return false; } - - CFTypeRef security_items = nullptr; - if (SecItemCopyMatching(query.get(), &security_items) != errSecSuccess || - CFArrayGetTypeID() != CFGetTypeID(security_items)) { - return false; - } - - certs.reset(reinterpret_cast(security_items)); - return true; -} - -inline bool retrieve_root_certs_from_keychain(CFObjectPtr &certs) { - CFArrayRef root_security_items = nullptr; - if (SecTrustCopyAnchorCertificates(&root_security_items) != errSecSuccess) { - return false; - } - - certs.reset(root_security_items); - return true; -} - -inline bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) { - auto result = false; - for (int i = 0; i < CFArrayGetCount(certs); ++i) { - const auto cert = reinterpret_cast( - CFArrayGetValueAtIndex(certs, i)); - - if (SecCertificateGetTypeID() != CFGetTypeID(cert)) { continue; } - - CFDataRef cert_data = nullptr; - if (SecItemExport(cert, kSecFormatX509Cert, 0, nullptr, &cert_data) != - errSecSuccess) { - continue; - } - - CFObjectPtr cert_data_ptr(cert_data, cf_object_ptr_deleter); - - auto encoded_cert = static_cast( - CFDataGetBytePtr(cert_data_ptr.get())); - - auto x509 = - d2i_X509(NULL, &encoded_cert, CFDataGetLength(cert_data_ptr.get())); - - if (x509) { - X509_STORE_add_cert(store, x509); - X509_free(x509); - result = true; - } - } - - return result; -} - -inline bool load_system_certs_on_macos(X509_STORE *store) { - auto result = false; - CFObjectPtr certs(nullptr, cf_object_ptr_deleter); - if (retrieve_certs_from_keychain(certs) && certs) { - result = add_certs_to_x509_store(certs.get(), store); - } - - if (retrieve_root_certs_from_keychain(certs) && certs) { - result = add_certs_to_x509_store(certs.get(), store) || result; - } - - return result; -} -#endif // TARGET_OS_OSX -#endif // _WIN32 -#endif // CPPHTTPLIB_OPENSSL_SUPPORT - -#ifdef _WIN32 -class WSInit { -public: - WSInit() { - WSADATA wsaData; - if (WSAStartup(0x0002, &wsaData) == 0) is_valid_ = true; - } - - ~WSInit() { - if (is_valid_) WSACleanup(); - } - - bool is_valid_ = false; -}; - -static WSInit wsinit_; -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline std::pair make_digest_authentication_header( - const Request &req, const std::map &auth, - size_t cnonce_count, const std::string &cnonce, const std::string &username, - const std::string &password, bool is_proxy = false) { - std::string nc; - { - std::stringstream ss; - ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count; - nc = ss.str(); - } - - std::string qop; - if (auth.find("qop") != auth.end()) { - qop = auth.at("qop"); - if (qop.find("auth-int") != std::string::npos) { - qop = "auth-int"; - } else if (qop.find("auth") != std::string::npos) { - qop = "auth"; - } else { - qop.clear(); - } - } - - std::string algo = "MD5"; - if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); } - - std::string response; - { - auto H = algo == "SHA-256" ? detail::SHA_256 - : algo == "SHA-512" ? detail::SHA_512 - : detail::MD5; - - auto A1 = username + ":" + auth.at("realm") + ":" + password; - - auto A2 = req.method + ":" + req.path; - if (qop == "auth-int") { A2 += ":" + H(req.body); } - - if (qop.empty()) { - response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2)); - } else { - response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce + - ":" + qop + ":" + H(A2)); - } - } - - auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : ""; - - auto field = "Digest username=\"" + username + "\", realm=\"" + - auth.at("realm") + "\", nonce=\"" + auth.at("nonce") + - "\", uri=\"" + req.path + "\", algorithm=" + algo + - (qop.empty() ? ", response=\"" - : ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" + - cnonce + "\", response=\"") + - response + "\"" + - (opaque.empty() ? "" : ", opaque=\"" + opaque + "\""); - - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, field); -} -#endif - -inline bool parse_www_authenticate(const Response &res, - std::map &auth, - bool is_proxy) { - auto auth_key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate"; - if (res.has_header(auth_key)) { - static auto re = std::regex(R"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~"); - auto s = res.get_header_value(auth_key); - auto pos = s.find(' '); - if (pos != std::string::npos) { - auto type = s.substr(0, pos); - if (type == "Basic") { - return false; - } else if (type == "Digest") { - s = s.substr(pos + 1); - auto beg = std::sregex_iterator(s.begin(), s.end(), re); - for (auto i = beg; i != std::sregex_iterator(); ++i) { - auto m = *i; - auto key = s.substr(static_cast(m.position(1)), - static_cast(m.length(1))); - auto val = m.length(2) > 0 - ? s.substr(static_cast(m.position(2)), - static_cast(m.length(2))) - : s.substr(static_cast(m.position(3)), - static_cast(m.length(3))); - auth[key] = val; - } - return true; - } - } - } - return false; -} - -// https://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c/440240#answer-440240 -inline std::string random_string(size_t length) { - auto randchar = []() -> char { - const char charset[] = "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const size_t max_index = (sizeof(charset) - 1); - return charset[static_cast(std::rand()) % max_index]; - }; - std::string str(length, 0); - std::generate_n(str.begin(), length, randchar); - return str; -} - -class ContentProviderAdapter { -public: - explicit ContentProviderAdapter( - ContentProviderWithoutLength &&content_provider) - : content_provider_(content_provider) {} - - bool operator()(size_t offset, size_t, DataSink &sink) { - return content_provider_(offset, sink); - } - -private: - ContentProviderWithoutLength content_provider_; -}; - -} // namespace detail - -inline std::string hosted_at(const std::string &hostname) { - std::vector addrs; - hosted_at(hostname, addrs); - if (addrs.empty()) { return std::string(); } - return addrs[0]; -} - -inline void hosted_at(const std::string &hostname, - std::vector &addrs) { - struct addrinfo hints; - struct addrinfo *result; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result)) { -#if defined __linux__ && !defined __ANDROID__ - res_init(); -#endif - return; - } - - for (auto rp = result; rp; rp = rp->ai_next) { - const auto &addr = - *reinterpret_cast(rp->ai_addr); - std::string ip; - int dummy = -1; - if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), ip, - dummy)) { - addrs.push_back(ip); - } - } - - freeaddrinfo(result); -} - -inline std::string append_query_params(const std::string &path, - const Params ¶ms) { - std::string path_with_query = path; - const static std::regex re("[^?]+\\?.*"); - auto delm = std::regex_match(path, re) ? '&' : '?'; - path_with_query += delm + detail::params_to_query_str(params); - return path_with_query; -} - -// Header utilities -inline std::pair make_range_header(Ranges ranges) { - std::string field = "bytes="; - auto i = 0; - for (auto r : ranges) { - if (i != 0) { field += ", "; } - if (r.first != -1) { field += std::to_string(r.first); } - field += '-'; - if (r.second != -1) { field += std::to_string(r.second); } - i++; - } - return std::make_pair("Range", std::move(field)); -} - -inline std::pair -make_basic_authentication_header(const std::string &username, - const std::string &password, bool is_proxy) { - auto field = "Basic " + detail::base64_encode(username + ":" + password); - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, std::move(field)); -} - -inline std::pair -make_bearer_token_authentication_header(const std::string &token, - bool is_proxy = false) { - auto field = "Bearer " + token; - auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; - return std::make_pair(key, std::move(field)); -} - -// Request implementation -inline bool Request::has_header(const std::string &key) const { - return detail::has_header(headers, key); -} - -inline std::string Request::get_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(headers, key, id, ""); -} - -inline size_t Request::get_header_value_count(const std::string &key) const { - auto r = headers.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline void Request::set_header(const std::string &key, - const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val)) { - headers.emplace(key, val); - } -} - -inline bool Request::has_param(const std::string &key) const { - return params.find(key) != params.end(); -} - -inline std::string Request::get_param_value(const std::string &key, - size_t id) const { - auto rng = params.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { return it->second; } - return std::string(); -} - -inline size_t Request::get_param_value_count(const std::string &key) const { - auto r = params.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline bool Request::is_multipart_form_data() const { - const auto &content_type = get_header_value("Content-Type"); - return !content_type.rfind("multipart/form-data", 0); -} - -inline bool Request::has_file(const std::string &key) const { - return files.find(key) != files.end(); -} - -inline MultipartFormData Request::get_file_value(const std::string &key) const { - auto it = files.find(key); - if (it != files.end()) { return it->second; } - return MultipartFormData(); -} - -inline std::vector -Request::get_file_values(const std::string &key) const { - std::vector values; - auto rng = files.equal_range(key); - for (auto it = rng.first; it != rng.second; it++) { - values.push_back(it->second); - } - return values; -} - -// Response implementation -inline bool Response::has_header(const std::string &key) const { - return headers.find(key) != headers.end(); -} - -inline std::string Response::get_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(headers, key, id, ""); -} - -inline size_t Response::get_header_value_count(const std::string &key) const { - auto r = headers.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -inline void Response::set_header(const std::string &key, - const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val)) { - headers.emplace(key, val); - } -} - -inline void Response::set_redirect(const std::string &url, int stat) { - if (!detail::has_crlf(url)) { - set_header("Location", url); - if (300 <= stat && stat < 400) { - this->status = stat; - } else { - this->status = 302; - } - } -} - -inline void Response::set_content(const char *s, size_t n, - const std::string &content_type) { - body.assign(s, n); - - auto rng = headers.equal_range("Content-Type"); - headers.erase(rng.first, rng.second); - set_header("Content-Type", content_type); -} - -inline void Response::set_content(const std::string &s, - const std::string &content_type) { - set_content(s.data(), s.size(), content_type); -} - -inline void Response::set_content_provider( - size_t in_length, const std::string &content_type, ContentProvider provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = in_length; - if (in_length > 0) { content_provider_ = std::move(provider); } - content_provider_resource_releaser_ = resource_releaser; - is_chunked_content_provider_ = false; -} - -inline void Response::set_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = 0; - content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = resource_releaser; - is_chunked_content_provider_ = false; -} - -inline void Response::set_chunked_content_provider( - const std::string &content_type, ContentProviderWithoutLength provider, - ContentProviderResourceReleaser resource_releaser) { - set_header("Content-Type", content_type); - content_length_ = 0; - content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = resource_releaser; - is_chunked_content_provider_ = true; -} - -// Result implementation -inline bool Result::has_request_header(const std::string &key) const { - return request_headers_.find(key) != request_headers_.end(); -} - -inline std::string Result::get_request_header_value(const std::string &key, - size_t id) const { - return detail::get_header_value(request_headers_, key, id, ""); -} - -inline size_t -Result::get_request_header_value_count(const std::string &key) const { - auto r = request_headers_.equal_range(key); - return static_cast(std::distance(r.first, r.second)); -} - -// Stream implementation -inline ssize_t Stream::write(const char *ptr) { - return write(ptr, strlen(ptr)); -} - -inline ssize_t Stream::write(const std::string &s) { - return write(s.data(), s.size()); -} - -namespace detail { - -// Socket stream implementation -inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec) - : sock_(sock), read_timeout_sec_(read_timeout_sec), - read_timeout_usec_(read_timeout_usec), - write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {} - -inline SocketStream::~SocketStream() {} - -inline bool SocketStream::is_readable() const { - return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; -} - -inline bool SocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && - is_socket_alive(sock_); -} - -inline ssize_t SocketStream::read(char *ptr, size_t size) { -#ifdef _WIN32 - size = - (std::min)(size, static_cast((std::numeric_limits::max)())); -#else - size = (std::min)(size, - static_cast((std::numeric_limits::max)())); -#endif - - if (read_buff_off_ < read_buff_content_size_) { - auto remaining_size = read_buff_content_size_ - read_buff_off_; - if (size <= remaining_size) { - memcpy(ptr, read_buff_.data() + read_buff_off_, size); - read_buff_off_ += size; - return static_cast(size); - } else { - memcpy(ptr, read_buff_.data() + read_buff_off_, remaining_size); - read_buff_off_ += remaining_size; - return static_cast(remaining_size); - } - } - - if (!is_readable()) { return -1; } - - read_buff_off_ = 0; - read_buff_content_size_ = 0; - - if (size < read_buff_size_) { - auto n = read_socket(sock_, read_buff_.data(), read_buff_size_, - CPPHTTPLIB_RECV_FLAGS); - if (n <= 0) { - return n; - } else if (n <= static_cast(size)) { - memcpy(ptr, read_buff_.data(), static_cast(n)); - return n; - } else { - memcpy(ptr, read_buff_.data(), size); - read_buff_off_ = size; - read_buff_content_size_ = static_cast(n); - return static_cast(size); - } - } else { - return read_socket(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); - } -} - -inline ssize_t SocketStream::write(const char *ptr, size_t size) { - if (!is_writable()) { return -1; } - -#if defined(_WIN32) && !defined(_WIN64) - size = - (std::min)(size, static_cast((std::numeric_limits::max)())); -#endif - - return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); -} - -inline void SocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - return detail::get_remote_ip_and_port(sock_, ip, port); -} - -inline void SocketStream::get_local_ip_and_port(std::string &ip, - int &port) const { - return detail::get_local_ip_and_port(sock_, ip, port); -} - -inline socket_t SocketStream::socket() const { return sock_; } - -// Buffer stream implementation -inline bool BufferStream::is_readable() const { return true; } - -inline bool BufferStream::is_writable() const { return true; } - -inline ssize_t BufferStream::read(char *ptr, size_t size) { -#if defined(_MSC_VER) && _MSC_VER < 1910 - auto len_read = buffer._Copy_s(ptr, size, size, position); -#else - auto len_read = buffer.copy(ptr, size, position); -#endif - position += static_cast(len_read); - return static_cast(len_read); -} - -inline ssize_t BufferStream::write(const char *ptr, size_t size) { - buffer.append(ptr, size); - return static_cast(size); -} - -inline void BufferStream::get_remote_ip_and_port(std::string & /*ip*/, - int & /*port*/) const {} - -inline void BufferStream::get_local_ip_and_port(std::string & /*ip*/, - int & /*port*/) const {} - -inline socket_t BufferStream::socket() const { return 0; } - -inline const std::string &BufferStream::get_buffer() const { return buffer; } - -} // namespace detail - -// HTTP server implementation -inline Server::Server() - : new_task_queue( - [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif -} - -inline Server::~Server() {} - -inline Server &Server::Get(const std::string &pattern, Handler handler) { - get_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Post(const std::string &pattern, Handler handler) { - post_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Post(const std::string &pattern, - HandlerWithContentReader handler) { - post_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Put(const std::string &pattern, Handler handler) { - put_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Put(const std::string &pattern, - HandlerWithContentReader handler) { - put_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Patch(const std::string &pattern, Handler handler) { - patch_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Patch(const std::string &pattern, - HandlerWithContentReader handler) { - patch_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Delete(const std::string &pattern, Handler handler) { - delete_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Delete(const std::string &pattern, - HandlerWithContentReader handler) { - delete_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline Server &Server::Options(const std::string &pattern, Handler handler) { - options_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); - return *this; -} - -inline bool Server::set_base_dir(const std::string &dir, - const std::string &mount_point) { - return set_mount_point(mount_point, dir); -} - -inline bool Server::set_mount_point(const std::string &mount_point, - const std::string &dir, Headers headers) { - if (detail::is_dir(dir)) { - std::string mnt = !mount_point.empty() ? mount_point : "/"; - if (!mnt.empty() && mnt[0] == '/') { - base_dirs_.push_back({mnt, dir, std::move(headers)}); - return true; - } - } - return false; -} - -inline bool Server::remove_mount_point(const std::string &mount_point) { - for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) { - if (it->mount_point == mount_point) { - base_dirs_.erase(it); - return true; - } - } - return false; -} - -inline Server & -Server::set_file_extension_and_mimetype_mapping(const std::string &ext, - const std::string &mime) { - file_extension_and_mimetype_map_[ext] = mime; - return *this; -} - -inline Server &Server::set_file_request_handler(Handler handler) { - file_request_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_error_handler(HandlerWithResponse handler) { - error_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_error_handler(Handler handler) { - error_handler_ = [handler](const Request &req, Response &res) { - handler(req, res); - return HandlerResponse::Handled; - }; - return *this; -} - -inline Server &Server::set_exception_handler(ExceptionHandler handler) { - exception_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_pre_routing_handler(HandlerWithResponse handler) { - pre_routing_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_post_routing_handler(Handler handler) { - post_routing_handler_ = std::move(handler); - return *this; -} - -inline Server &Server::set_logger(Logger logger) { - logger_ = std::move(logger); - return *this; -} - -inline Server & -Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) { - expect_100_continue_handler_ = std::move(handler); - - return *this; -} - -inline Server &Server::set_address_family(int family) { - address_family_ = family; - return *this; -} - -inline Server &Server::set_tcp_nodelay(bool on) { - tcp_nodelay_ = on; - return *this; -} - -inline Server &Server::set_socket_options(SocketOptions socket_options) { - socket_options_ = std::move(socket_options); - return *this; -} - -inline Server &Server::set_default_headers(Headers headers) { - default_headers_ = std::move(headers); - return *this; -} - -inline Server &Server::set_keep_alive_max_count(size_t count) { - keep_alive_max_count_ = count; - return *this; -} - -inline Server &Server::set_keep_alive_timeout(time_t sec) { - keep_alive_timeout_sec_ = sec; - return *this; -} - -inline Server &Server::set_read_timeout(time_t sec, time_t usec) { - read_timeout_sec_ = sec; - read_timeout_usec_ = usec; - return *this; -} - -inline Server &Server::set_write_timeout(time_t sec, time_t usec) { - write_timeout_sec_ = sec; - write_timeout_usec_ = usec; - return *this; -} - -inline Server &Server::set_idle_interval(time_t sec, time_t usec) { - idle_interval_sec_ = sec; - idle_interval_usec_ = usec; - return *this; -} - -inline Server &Server::set_payload_max_length(size_t length) { - payload_max_length_ = length; - return *this; -} - -inline bool Server::bind_to_port(const std::string &host, int port, - int socket_flags) { - if (bind_internal(host, port, socket_flags) < 0) return false; - return true; -} -inline int Server::bind_to_any_port(const std::string &host, int socket_flags) { - return bind_internal(host, 0, socket_flags); -} - -inline bool Server::listen_after_bind() { - auto se = detail::scope_exit([&]() { done_ = true; }); - return listen_internal(); -} - -inline bool Server::listen(const std::string &host, int port, - int socket_flags) { - auto se = detail::scope_exit([&]() { done_ = true; }); - return bind_to_port(host, port, socket_flags) && listen_internal(); -} - -inline bool Server::is_running() const { return is_running_; } - -inline void Server::wait_until_ready() const { - while (!is_running() && !done_) { - std::this_thread::sleep_for(std::chrono::milliseconds{1}); - } -} - -inline void Server::stop() { - if (is_running_) { - assert(svr_sock_ != INVALID_SOCKET); - std::atomic sock(svr_sock_.exchange(INVALID_SOCKET)); - detail::shutdown_socket(sock); - detail::close_socket(sock); - } -} - -inline bool Server::parse_request_line(const char *s, Request &req) { - auto len = strlen(s); - if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; } - len -= 2; - - { - size_t count = 0; - - detail::split(s, s + len, ' ', [&](const char *b, const char *e) { - switch (count) { - case 0: req.method = std::string(b, e); break; - case 1: req.target = std::string(b, e); break; - case 2: req.version = std::string(b, e); break; - default: break; - } - count++; - }); - - if (count != 3) { return false; } - } - - static const std::set methods{ - "GET", "HEAD", "POST", "PUT", "DELETE", - "CONNECT", "OPTIONS", "TRACE", "PATCH", "PRI"}; - - if (methods.find(req.method) == methods.end()) { return false; } - - if (req.version != "HTTP/1.1" && req.version != "HTTP/1.0") { return false; } - - { - // Skip URL fragment - for (size_t i = 0; i < req.target.size(); i++) { - if (req.target[i] == '#') { - req.target.erase(i); - break; - } - } - - size_t count = 0; - - detail::split(req.target.data(), req.target.data() + req.target.size(), '?', - [&](const char *b, const char *e) { - switch (count) { - case 0: - req.path = detail::decode_url(std::string(b, e), false); - break; - case 1: { - if (e - b > 0) { - detail::parse_query_text(std::string(b, e), req.params); - } - break; - } - default: break; - } - count++; - }); - - if (count > 2) { return false; } - } - - return true; -} - -inline bool Server::write_response(Stream &strm, bool close_connection, - const Request &req, Response &res) { - return write_response_core(strm, close_connection, req, res, false); -} - -inline bool Server::write_response_with_content(Stream &strm, - bool close_connection, - const Request &req, - Response &res) { - return write_response_core(strm, close_connection, req, res, true); -} - -inline bool Server::write_response_core(Stream &strm, bool close_connection, - const Request &req, Response &res, - bool need_apply_ranges) { - assert(res.status != -1); - - if (400 <= res.status && error_handler_ && - error_handler_(req, res) == HandlerResponse::Handled) { - need_apply_ranges = true; - } - - std::string content_type; - std::string boundary; - if (need_apply_ranges) { apply_ranges(req, res, content_type, boundary); } - - // Prepare additional headers - if (close_connection || req.get_header_value("Connection") == "close") { - res.set_header("Connection", "close"); - } else { - std::stringstream ss; - ss << "timeout=" << keep_alive_timeout_sec_ - << ", max=" << keep_alive_max_count_; - res.set_header("Keep-Alive", ss.str()); - } - - if (!res.has_header("Content-Type") && - (!res.body.empty() || res.content_length_ > 0 || res.content_provider_)) { - res.set_header("Content-Type", "text/plain"); - } - - if (!res.has_header("Content-Length") && res.body.empty() && - !res.content_length_ && !res.content_provider_) { - res.set_header("Content-Length", "0"); - } - - if (!res.has_header("Accept-Ranges") && req.method == "HEAD") { - res.set_header("Accept-Ranges", "bytes"); - } - - if (post_routing_handler_) { post_routing_handler_(req, res); } - - // Response line and headers - { - detail::BufferStream bstrm; - - if (!bstrm.write_format("HTTP/1.1 %d %s\r\n", res.status, - detail::status_message(res.status))) { - return false; - } - - if (!detail::write_headers(bstrm, res.headers)) { return false; } - - // Flush buffer - auto &data = bstrm.get_buffer(); - detail::write_data(strm, data.data(), data.size()); - } - - // Body - auto ret = true; - if (req.method != "HEAD") { - if (!res.body.empty()) { - if (!detail::write_data(strm, res.body.data(), res.body.size())) { - ret = false; - } - } else if (res.content_provider_) { - if (write_content_with_provider(strm, req, res, boundary, content_type)) { - res.content_provider_success_ = true; - } else { - res.content_provider_success_ = false; - ret = false; - } - } - } - - // Log - if (logger_) { logger_(req, res); } - - return ret; -} - -inline bool -Server::write_content_with_provider(Stream &strm, const Request &req, - Response &res, const std::string &boundary, - const std::string &content_type) { - auto is_shutting_down = [this]() { - return this->svr_sock_ == INVALID_SOCKET; - }; - - if (res.content_length_ > 0) { - if (req.ranges.empty()) { - return detail::write_content(strm, res.content_provider_, 0, - res.content_length_, is_shutting_down); - } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.content_length_, 0); - auto offset = offsets.first; - auto length = offsets.second; - return detail::write_content(strm, res.content_provider_, offset, length, - is_shutting_down); - } else { - return detail::write_multipart_ranges_data( - strm, req, res, boundary, content_type, is_shutting_down); - } - } else { - if (res.is_chunked_content_provider_) { - auto type = detail::encoding_type(req, res); - - std::unique_ptr compressor; - if (type == detail::EncodingType::Gzip) { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = detail::make_unique(); -#endif - } else if (type == detail::EncodingType::Brotli) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = detail::make_unique(); -#endif - } else { - compressor = detail::make_unique(); - } - assert(compressor != nullptr); - - return detail::write_content_chunked(strm, res.content_provider_, - is_shutting_down, *compressor); - } else { - return detail::write_content_without_length(strm, res.content_provider_, - is_shutting_down); - } - } -} - -inline bool Server::read_content(Stream &strm, Request &req, Response &res) { - MultipartFormDataMap::iterator cur; - auto file_count = 0; - if (read_content_core( - strm, req, res, - // Regular - [&](const char *buf, size_t n) { - if (req.body.size() + n > req.body.max_size()) { return false; } - req.body.append(buf, n); - return true; - }, - // Multipart - [&](const MultipartFormData &file) { - if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) { - return false; - } - cur = req.files.emplace(file.name, file); - return true; - }, - [&](const char *buf, size_t n) { - auto &content = cur->second.content; - if (content.size() + n > content.max_size()) { return false; } - content.append(buf, n); - return true; - })) { - const auto &content_type = req.get_header_value("Content-Type"); - if (!content_type.find("application/x-www-form-urlencoded")) { - if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) { - res.status = 413; // NOTE: should be 414? - return false; - } - detail::parse_query_text(req.body, req.params); - } - return true; - } - return false; -} - -inline bool Server::read_content_with_content_receiver( - Stream &strm, Request &req, Response &res, ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver) { - return read_content_core(strm, req, res, std::move(receiver), - std::move(multipart_header), - std::move(multipart_receiver)); -} - -inline bool Server::read_content_core(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader multipart_header, - ContentReceiver multipart_receiver) { - detail::MultipartFormDataParser multipart_form_data_parser; - ContentReceiverWithProgress out; - - if (req.is_multipart_form_data()) { - const auto &content_type = req.get_header_value("Content-Type"); - std::string boundary; - if (!detail::parse_multipart_boundary(content_type, boundary)) { - res.status = 400; - return false; - } - - multipart_form_data_parser.set_boundary(std::move(boundary)); - out = [&](const char *buf, size_t n, uint64_t /*off*/, uint64_t /*len*/) { - /* For debug - size_t pos = 0; - while (pos < n) { - auto read_size = (std::min)(1, n - pos); - auto ret = multipart_form_data_parser.parse( - buf + pos, read_size, multipart_receiver, multipart_header); - if (!ret) { return false; } - pos += read_size; - } - return true; - */ - return multipart_form_data_parser.parse(buf, n, multipart_receiver, - multipart_header); - }; - } else { - out = [receiver](const char *buf, size_t n, uint64_t /*off*/, - uint64_t /*len*/) { return receiver(buf, n); }; - } - - if (req.method == "DELETE" && !req.has_header("Content-Length")) { - return true; - } - - if (!detail::read_content(strm, req, payload_max_length_, res.status, nullptr, - out, true)) { - return false; - } - - if (req.is_multipart_form_data()) { - if (!multipart_form_data_parser.is_valid()) { - res.status = 400; - return false; - } - } - - return true; -} - -inline bool Server::handle_file_request(const Request &req, Response &res, - bool head) { - for (const auto &entry : base_dirs_) { - // Prefix match - if (!req.path.compare(0, entry.mount_point.size(), entry.mount_point)) { - std::string sub_path = "/" + req.path.substr(entry.mount_point.size()); - if (detail::is_valid_path(sub_path)) { - auto path = entry.base_dir + sub_path; - if (path.back() == '/') { path += "index.html"; } - - if (detail::is_file(path)) { - detail::read_file(path, res.body); - auto type = - detail::find_content_type(path, file_extension_and_mimetype_map_); - if (type) { res.set_header("Content-Type", type); } - for (const auto &kv : entry.headers) { - res.set_header(kv.first.c_str(), kv.second); - } - res.status = req.has_header("Range") ? 206 : 200; - if (!head && file_request_handler_) { - file_request_handler_(req, res); - } - return true; - } - } - } - } - return false; -} - -inline socket_t -Server::create_server_socket(const std::string &host, int port, - int socket_flags, - SocketOptions socket_options) const { - return detail::create_socket( - host, std::string(), port, address_family_, socket_flags, tcp_nodelay_, - std::move(socket_options), - [](socket_t sock, struct addrinfo &ai) -> bool { - if (::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { - return false; - } - if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false; } - return true; - }); -} - -inline int Server::bind_internal(const std::string &host, int port, - int socket_flags) { - if (!is_valid()) { return -1; } - - svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_); - if (svr_sock_ == INVALID_SOCKET) { return -1; } - - if (port == 0) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - if (getsockname(svr_sock_, reinterpret_cast(&addr), - &addr_len) == -1) { - return -1; - } - if (addr.ss_family == AF_INET) { - return ntohs(reinterpret_cast(&addr)->sin_port); - } else if (addr.ss_family == AF_INET6) { - return ntohs(reinterpret_cast(&addr)->sin6_port); - } else { - return -1; - } - } else { - return port; - } -} - -inline bool Server::listen_internal() { - auto ret = true; - is_running_ = true; - auto se = detail::scope_exit([&]() { is_running_ = false; }); - - { - std::unique_ptr task_queue(new_task_queue()); - - while (svr_sock_ != INVALID_SOCKET) { -#ifndef _WIN32 - if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) { -#endif - auto val = detail::select_read(svr_sock_, idle_interval_sec_, - idle_interval_usec_); - if (val == 0) { // Timeout - task_queue->on_idle(); - continue; - } -#ifndef _WIN32 - } -#endif - socket_t sock = accept(svr_sock_, nullptr, nullptr); - - if (sock == INVALID_SOCKET) { - if (errno == EMFILE) { - // The per-process limit of open file descriptors has been reached. - // Try to accept new connections after a short sleep. - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - continue; - } else if (errno == EINTR || errno == EAGAIN) { - continue; - } - if (svr_sock_ != INVALID_SOCKET) { - detail::close_socket(svr_sock_); - ret = false; - } else { - ; // The server socket was closed by user. - } - break; - } - - { -#ifdef _WIN32 - auto timeout = static_cast(read_timeout_sec_ * 1000 + - read_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(read_timeout_sec_); - tv.tv_usec = static_cast(read_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); -#endif - } - { - -#ifdef _WIN32 - auto timeout = static_cast(write_timeout_sec_ * 1000 + - write_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, - sizeof(timeout)); -#else - timeval tv; - tv.tv_sec = static_cast(write_timeout_sec_); - tv.tv_usec = static_cast(write_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); -#endif - } - - task_queue->enqueue([this, sock]() { process_and_close_socket(sock); }); - } - - task_queue->shutdown(); - } - - return ret; -} - -inline bool Server::routing(Request &req, Response &res, Stream &strm) { - if (pre_routing_handler_ && - pre_routing_handler_(req, res) == HandlerResponse::Handled) { - return true; - } - - // File handler - bool is_head_request = req.method == "HEAD"; - if ((req.method == "GET" || is_head_request) && - handle_file_request(req, res, is_head_request)) { - return true; - } - - if (detail::expect_content(req)) { - // Content reader handler - { - ContentReader reader( - [&](ContentReceiver receiver) { - return read_content_with_content_receiver( - strm, req, res, std::move(receiver), nullptr, nullptr); - }, - [&](MultipartContentHeader header, ContentReceiver receiver) { - return read_content_with_content_receiver(strm, req, res, nullptr, - std::move(header), - std::move(receiver)); - }); - - if (req.method == "POST") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - post_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "PUT") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - put_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "PATCH") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - patch_handlers_for_content_reader_)) { - return true; - } - } else if (req.method == "DELETE") { - if (dispatch_request_for_content_reader( - req, res, std::move(reader), - delete_handlers_for_content_reader_)) { - return true; - } - } - } - - // Read content into `req.body` - if (!read_content(strm, req, res)) { return false; } - } - - // Regular handler - if (req.method == "GET" || req.method == "HEAD") { - return dispatch_request(req, res, get_handlers_); - } else if (req.method == "POST") { - return dispatch_request(req, res, post_handlers_); - } else if (req.method == "PUT") { - return dispatch_request(req, res, put_handlers_); - } else if (req.method == "DELETE") { - return dispatch_request(req, res, delete_handlers_); - } else if (req.method == "OPTIONS") { - return dispatch_request(req, res, options_handlers_); - } else if (req.method == "PATCH") { - return dispatch_request(req, res, patch_handlers_); - } - - res.status = 400; - return false; -} - -inline bool Server::dispatch_request(Request &req, Response &res, - const Handlers &handlers) { - for (const auto &x : handlers) { - const auto &pattern = x.first; - const auto &handler = x.second; - - if (std::regex_match(req.path, req.matches, pattern)) { - handler(req, res); - return true; - } - } - return false; -} - -inline void Server::apply_ranges(const Request &req, Response &res, - std::string &content_type, - std::string &boundary) { - if (req.ranges.size() > 1) { - boundary = detail::make_multipart_data_boundary(); - - auto it = res.headers.find("Content-Type"); - if (it != res.headers.end()) { - content_type = it->second; - res.headers.erase(it); - } - - res.headers.emplace("Content-Type", - "multipart/byteranges; boundary=" + boundary); - } - - auto type = detail::encoding_type(req, res); - - if (res.body.empty()) { - if (res.content_length_ > 0) { - size_t length = 0; - if (req.ranges.empty()) { - length = res.content_length_; - } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.content_length_, 0); - auto offset = offsets.first; - length = offsets.second; - auto content_range = detail::make_content_range_header_field( - offset, length, res.content_length_); - res.set_header("Content-Range", content_range); - } else { - length = detail::get_multipart_ranges_data_length(req, res, boundary, - content_type); - } - res.set_header("Content-Length", std::to_string(length)); - } else { - if (res.content_provider_) { - if (res.is_chunked_content_provider_) { - res.set_header("Transfer-Encoding", "chunked"); - if (type == detail::EncodingType::Gzip) { - res.set_header("Content-Encoding", "gzip"); - } else if (type == detail::EncodingType::Brotli) { - res.set_header("Content-Encoding", "br"); - } - } - } - } - } else { - if (req.ranges.empty()) { - ; - } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.body.size(), 0); - auto offset = offsets.first; - auto length = offsets.second; - auto content_range = detail::make_content_range_header_field( - offset, length, res.body.size()); - res.set_header("Content-Range", content_range); - if (offset < res.body.size()) { - res.body = res.body.substr(offset, length); - } else { - res.body.clear(); - res.status = 416; - } - } else { - std::string data; - if (detail::make_multipart_ranges_data(req, res, boundary, content_type, - data)) { - res.body.swap(data); - } else { - res.body.clear(); - res.status = 416; - } - } - - if (type != detail::EncodingType::None) { - std::unique_ptr compressor; - std::string content_encoding; - - if (type == detail::EncodingType::Gzip) { -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = detail::make_unique(); - content_encoding = "gzip"; -#endif - } else if (type == detail::EncodingType::Brotli) { -#ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = detail::make_unique(); - content_encoding = "br"; -#endif - } - - if (compressor) { - std::string compressed; - if (compressor->compress(res.body.data(), res.body.size(), true, - [&](const char *data, size_t data_len) { - compressed.append(data, data_len); - return true; - })) { - res.body.swap(compressed); - res.set_header("Content-Encoding", content_encoding); - } - } - } - - auto length = std::to_string(res.body.size()); - res.set_header("Content-Length", length); - } -} - -inline bool Server::dispatch_request_for_content_reader( - Request &req, Response &res, ContentReader content_reader, - const HandlersForContentReader &handlers) { - for (const auto &x : handlers) { - const auto &pattern = x.first; - const auto &handler = x.second; - - if (std::regex_match(req.path, req.matches, pattern)) { - handler(req, res, content_reader); - return true; - } - } - return false; -} - -inline bool -Server::process_request(Stream &strm, bool close_connection, - bool &connection_closed, - const std::function &setup_request) { - std::array buf{}; - - detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); - - // Connection has been closed on client - if (!line_reader.getline()) { return false; } - - Request req; - Response res; - - res.version = "HTTP/1.1"; - - for (const auto &header : default_headers_) { - if (res.headers.find(header.first) == res.headers.end()) { - res.headers.insert(header); - } - } - -#ifdef _WIN32 - // TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL). -#else -#ifndef CPPHTTPLIB_USE_POLL - // Socket file descriptor exceeded FD_SETSIZE... - if (strm.socket() >= FD_SETSIZE) { - Headers dummy; - detail::read_headers(strm, dummy); - res.status = 500; - return write_response(strm, close_connection, req, res); - } -#endif -#endif - - // Check if the request URI doesn't exceed the limit - if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { - Headers dummy; - detail::read_headers(strm, dummy); - res.status = 414; - return write_response(strm, close_connection, req, res); - } - - // Request line and headers - if (!parse_request_line(line_reader.ptr(), req) || - !detail::read_headers(strm, req.headers)) { - res.status = 400; - return write_response(strm, close_connection, req, res); - } - - if (req.get_header_value("Connection") == "close") { - connection_closed = true; - } - - if (req.version == "HTTP/1.0" && - req.get_header_value("Connection") != "Keep-Alive") { - connection_closed = true; - } - - strm.get_remote_ip_and_port(req.remote_addr, req.remote_port); - req.set_header("REMOTE_ADDR", req.remote_addr); - req.set_header("REMOTE_PORT", std::to_string(req.remote_port)); - - strm.get_local_ip_and_port(req.local_addr, req.local_port); - req.set_header("LOCAL_ADDR", req.local_addr); - req.set_header("LOCAL_PORT", std::to_string(req.local_port)); - - if (req.has_header("Range")) { - const auto &range_header_value = req.get_header_value("Range"); - if (!detail::parse_range_header(range_header_value, req.ranges)) { - res.status = 416; - return write_response(strm, close_connection, req, res); - } - } - - if (setup_request) { setup_request(req); } - - if (req.get_header_value("Expect") == "100-continue") { - auto status = 100; - if (expect_100_continue_handler_) { - status = expect_100_continue_handler_(req, res); - } - switch (status) { - case 100: - case 417: - strm.write_format("HTTP/1.1 %d %s\r\n\r\n", status, - detail::status_message(status)); - break; - default: return write_response(strm, close_connection, req, res); - } - } - - // Rounting - bool routed = false; -#ifdef CPPHTTPLIB_NO_EXCEPTIONS - routed = routing(req, res, strm); -#else - try { - routed = routing(req, res, strm); - } catch (std::exception &e) { - if (exception_handler_) { - auto ep = std::current_exception(); - exception_handler_(req, res, ep); - routed = true; - } else { - res.status = 500; - std::string val; - auto s = e.what(); - for (size_t i = 0; s[i]; i++) { - switch (s[i]) { - case '\r': val += "\\r"; break; - case '\n': val += "\\n"; break; - default: val += s[i]; break; - } - } - res.set_header("EXCEPTION_WHAT", val); - } - } catch (...) { - if (exception_handler_) { - auto ep = std::current_exception(); - exception_handler_(req, res, ep); - routed = true; - } else { - res.status = 500; - res.set_header("EXCEPTION_WHAT", "UNKNOWN"); - } - } -#endif - - if (routed) { - if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; } - return write_response_with_content(strm, close_connection, req, res); - } else { - if (res.status == -1) { res.status = 404; } - return write_response(strm, close_connection, req, res); - } -} - -inline bool Server::is_valid() const { return true; } - -inline bool Server::process_and_close_socket(socket_t sock) { - auto ret = detail::process_server_socket( - svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, - [this](Stream &strm, bool close_connection, bool &connection_closed) { - return process_request(strm, close_connection, connection_closed, - nullptr); - }); - - detail::shutdown_socket(sock); - detail::close_socket(sock); - return ret; -} - -// HTTP client implementation -inline ClientImpl::ClientImpl(const std::string &host) - : ClientImpl(host, 80, std::string(), std::string()) {} - -inline ClientImpl::ClientImpl(const std::string &host, int port) - : ClientImpl(host, port, std::string(), std::string()) {} - -inline ClientImpl::ClientImpl(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : host_(host), port_(port), - host_and_port_(adjust_host_string(host) + ":" + std::to_string(port)), - client_cert_path_(client_cert_path), client_key_path_(client_key_path) {} - -inline ClientImpl::~ClientImpl() { - std::lock_guard guard(socket_mutex_); - shutdown_socket(socket_); - close_socket(socket_); -} - -inline bool ClientImpl::is_valid() const { return true; } - -inline void ClientImpl::copy_settings(const ClientImpl &rhs) { - client_cert_path_ = rhs.client_cert_path_; - client_key_path_ = rhs.client_key_path_; - connection_timeout_sec_ = rhs.connection_timeout_sec_; - read_timeout_sec_ = rhs.read_timeout_sec_; - read_timeout_usec_ = rhs.read_timeout_usec_; - write_timeout_sec_ = rhs.write_timeout_sec_; - write_timeout_usec_ = rhs.write_timeout_usec_; - basic_auth_username_ = rhs.basic_auth_username_; - basic_auth_password_ = rhs.basic_auth_password_; - bearer_token_auth_token_ = rhs.bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - digest_auth_username_ = rhs.digest_auth_username_; - digest_auth_password_ = rhs.digest_auth_password_; -#endif - keep_alive_ = rhs.keep_alive_; - follow_location_ = rhs.follow_location_; - url_encode_ = rhs.url_encode_; - address_family_ = rhs.address_family_; - tcp_nodelay_ = rhs.tcp_nodelay_; - socket_options_ = rhs.socket_options_; - compress_ = rhs.compress_; - decompress_ = rhs.decompress_; - interface_ = rhs.interface_; - proxy_host_ = rhs.proxy_host_; - proxy_port_ = rhs.proxy_port_; - proxy_basic_auth_username_ = rhs.proxy_basic_auth_username_; - proxy_basic_auth_password_ = rhs.proxy_basic_auth_password_; - proxy_bearer_token_auth_token_ = rhs.proxy_bearer_token_auth_token_; -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_; - proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_; -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - ca_cert_file_path_ = rhs.ca_cert_file_path_; - ca_cert_dir_path_ = rhs.ca_cert_dir_path_; - ca_cert_store_ = rhs.ca_cert_store_; -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - server_certificate_verification_ = rhs.server_certificate_verification_; -#endif - logger_ = rhs.logger_; -} - -inline socket_t ClientImpl::create_client_socket(Error &error) const { - if (!proxy_host_.empty() && proxy_port_ != -1) { - return detail::create_client_socket( - proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_, - socket_options_, connection_timeout_sec_, connection_timeout_usec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, interface_, error); - } - - // Check is custom IP specified for host_ - std::string ip; - auto it = addr_map_.find(host_); - if (it != addr_map_.end()) ip = it->second; - - return detail::create_client_socket( - host_, ip, port_, address_family_, tcp_nodelay_, socket_options_, - connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, - read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, - error); -} - -inline bool ClientImpl::create_and_connect_socket(Socket &socket, - Error &error) { - auto sock = create_client_socket(error); - if (sock == INVALID_SOCKET) { return false; } - socket.sock = sock; - return true; -} - -inline void ClientImpl::shutdown_ssl(Socket & /*socket*/, - bool /*shutdown_gracefully*/) { - // If there are any requests in flight from threads other than us, then it's - // a thread-unsafe race because individual ssl* objects are not thread-safe. - assert(socket_requests_in_flight_ == 0 || - socket_requests_are_from_thread_ == std::this_thread::get_id()); -} - -inline void ClientImpl::shutdown_socket(Socket &socket) { - if (socket.sock == INVALID_SOCKET) { return; } - detail::shutdown_socket(socket.sock); -} - -inline void ClientImpl::close_socket(Socket &socket) { - // If there are requests in flight in another thread, usually closing - // the socket will be fine and they will simply receive an error when - // using the closed socket, but it is still a bug since rarely the OS - // may reassign the socket id to be used for a new socket, and then - // suddenly they will be operating on a live socket that is different - // than the one they intended! - assert(socket_requests_in_flight_ == 0 || - socket_requests_are_from_thread_ == std::this_thread::get_id()); - - // It is also a bug if this happens while SSL is still active -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - assert(socket.ssl == nullptr); -#endif - if (socket.sock == INVALID_SOCKET) { return; } - detail::close_socket(socket.sock); - socket.sock = INVALID_SOCKET; -} - -inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, - Response &res) { - std::array buf{}; - - detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); - - if (!line_reader.getline()) { return false; } - -#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR - const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); -#else - const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n"); -#endif - - std::cmatch m; - if (!std::regex_match(line_reader.ptr(), m, re)) { - return req.method == "CONNECT"; - } - res.version = std::string(m[1]); - res.status = std::stoi(std::string(m[2])); - res.reason = std::string(m[3]); - - // Ignore '100 Continue' - while (res.status == 100) { - if (!line_reader.getline()) { return false; } // CRLF - if (!line_reader.getline()) { return false; } // next response line - - if (!std::regex_match(line_reader.ptr(), m, re)) { return false; } - res.version = std::string(m[1]); - res.status = std::stoi(std::string(m[2])); - res.reason = std::string(m[3]); - } - - return true; -} - -inline bool ClientImpl::send(Request &req, Response &res, Error &error) { - std::lock_guard request_mutex_guard(request_mutex_); - auto ret = send_(req, res, error); - if (error == Error::SSLPeerCouldBeClosed_) { - assert(!ret); - ret = send_(req, res, error); - } - return ret; -} - -inline bool ClientImpl::send_(Request &req, Response &res, Error &error) { - { - std::lock_guard guard(socket_mutex_); - - // Set this to false immediately - if it ever gets set to true by the end of - // the request, we know another thread instructed us to close the socket. - socket_should_be_closed_when_request_is_done_ = false; - - auto is_alive = false; - if (socket_.is_open()) { - is_alive = detail::is_socket_alive(socket_.sock); - if (!is_alive) { - // Attempt to avoid sigpipe by shutting down nongracefully if it seems - // like the other side has already closed the connection Also, there - // cannot be any requests in flight from other threads since we locked - // request_mutex_, so safe to close everything immediately - const bool shutdown_gracefully = false; - shutdown_ssl(socket_, shutdown_gracefully); - shutdown_socket(socket_); - close_socket(socket_); - } - } - - if (!is_alive) { - if (!create_and_connect_socket(socket_, error)) { return false; } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - // TODO: refactoring - if (is_ssl()) { - auto &scli = static_cast(*this); - if (!proxy_host_.empty() && proxy_port_ != -1) { - auto success = false; - if (!scli.connect_with_proxy(socket_, res, success, error)) { - return success; - } - } - - if (!scli.initialize_ssl(socket_, error)) { return false; } - } -#endif - } - - // Mark the current socket as being in use so that it cannot be closed by - // anyone else while this request is ongoing, even though we will be - // releasing the mutex. - if (socket_requests_in_flight_ > 1) { - assert(socket_requests_are_from_thread_ == std::this_thread::get_id()); - } - socket_requests_in_flight_ += 1; - socket_requests_are_from_thread_ = std::this_thread::get_id(); - } - - for (const auto &header : default_headers_) { - if (req.headers.find(header.first) == req.headers.end()) { - req.headers.insert(header); - } - } - - auto ret = false; - auto close_connection = !keep_alive_; - - auto se = detail::scope_exit([&]() { - // Briefly lock mutex in order to mark that a request is no longer ongoing - std::lock_guard guard(socket_mutex_); - socket_requests_in_flight_ -= 1; - if (socket_requests_in_flight_ <= 0) { - assert(socket_requests_in_flight_ == 0); - socket_requests_are_from_thread_ = std::thread::id(); - } - - if (socket_should_be_closed_when_request_is_done_ || close_connection || - !ret) { - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); - } - }); - - ret = process_socket(socket_, [&](Stream &strm) { - return handle_request(strm, req, res, close_connection, error); - }); - - if (!ret) { - if (error == Error::Success) { error = Error::Unknown; } - } - - return ret; -} - -inline Result ClientImpl::send(const Request &req) { - auto req2 = req; - return send_(std::move(req2)); -} - -inline Result ClientImpl::send_(Request &&req) { - auto res = detail::make_unique(); - auto error = Error::Success; - auto ret = send(req, *res, error); - return Result{ret ? std::move(res) : nullptr, error, std::move(req.headers)}; -} - -inline bool ClientImpl::handle_request(Stream &strm, Request &req, - Response &res, bool close_connection, - Error &error) { - if (req.path.empty()) { - error = Error::Connection; - return false; - } - - auto req_save = req; - - bool ret; - - if (!is_ssl() && !proxy_host_.empty() && proxy_port_ != -1) { - auto req2 = req; - req2.path = "http://" + host_and_port_ + req.path; - ret = process_request(strm, req2, res, close_connection, error); - req = req2; - req.path = req_save.path; - } else { - ret = process_request(strm, req, res, close_connection, error); - } - - if (!ret) { return false; } - - if (300 < res.status && res.status < 400 && follow_location_) { - req = req_save; - ret = redirect(req, res, error); - } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if ((res.status == 401 || res.status == 407) && - req.authorization_count_ < 5) { - auto is_proxy = res.status == 407; - const auto &username = - is_proxy ? proxy_digest_auth_username_ : digest_auth_username_; - const auto &password = - is_proxy ? proxy_digest_auth_password_ : digest_auth_password_; - - if (!username.empty() && !password.empty()) { - std::map auth; - if (detail::parse_www_authenticate(res, auth, is_proxy)) { - Request new_req = req; - new_req.authorization_count_ += 1; - new_req.headers.erase(is_proxy ? "Proxy-Authorization" - : "Authorization"); - new_req.headers.insert(detail::make_digest_authentication_header( - req, auth, new_req.authorization_count_, detail::random_string(10), - username, password, is_proxy)); - - Response new_res; - - ret = send(new_req, new_res, error); - if (ret) { res = new_res; } - } - } - } -#endif - - return ret; -} - -inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { - if (req.redirect_count_ == 0) { - error = Error::ExceedRedirectCount; - return false; - } - - auto location = res.get_header_value("location"); - if (location.empty()) { return false; } - - const static std::regex re( - R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)"); - - std::smatch m; - if (!std::regex_match(location, m, re)) { return false; } - - auto scheme = is_ssl() ? "https" : "http"; - - auto next_scheme = m[1].str(); - auto next_host = m[2].str(); - if (next_host.empty()) { next_host = m[3].str(); } - auto port_str = m[4].str(); - auto next_path = m[5].str(); - auto next_query = m[6].str(); - - auto next_port = port_; - if (!port_str.empty()) { - next_port = std::stoi(port_str); - } else if (!next_scheme.empty()) { - next_port = next_scheme == "https" ? 443 : 80; - } - - if (next_scheme.empty()) { next_scheme = scheme; } - if (next_host.empty()) { next_host = host_; } - if (next_path.empty()) { next_path = "/"; } - - auto path = detail::decode_url(next_path, true) + next_query; - - if (next_scheme == scheme && next_host == host_ && next_port == port_) { - return detail::redirect(*this, req, res, path, location, error); - } else { - if (next_scheme == "https") { -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - SSLClient cli(next_host.c_str(), next_port); - cli.copy_settings(*this); - if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); } - return detail::redirect(cli, req, res, path, location, error); -#else - return false; -#endif - } else { - ClientImpl cli(next_host.c_str(), next_port); - cli.copy_settings(*this); - return detail::redirect(cli, req, res, path, location, error); - } - } -} - -inline bool ClientImpl::write_content_with_provider(Stream &strm, - const Request &req, - Error &error) { - auto is_shutting_down = []() { return false; }; - - if (req.is_chunked_content_provider_) { - // TODO: Brotli support - std::unique_ptr compressor; -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_) { - compressor = detail::make_unique(); - } else -#endif - { - compressor = detail::make_unique(); - } - - return detail::write_content_chunked(strm, req.content_provider_, - is_shutting_down, *compressor, error); - } else { - return detail::write_content(strm, req.content_provider_, 0, - req.content_length_, is_shutting_down, error); - } -} - -inline bool ClientImpl::write_request(Stream &strm, Request &req, - bool close_connection, Error &error) { - // Prepare additional headers - if (close_connection) { - if (!req.has_header("Connection")) { - req.headers.emplace("Connection", "close"); - } - } - - if (!req.has_header("Host")) { - if (is_ssl()) { - if (port_ == 443) { - req.headers.emplace("Host", host_); - } else { - req.headers.emplace("Host", host_and_port_); - } - } else { - if (port_ == 80) { - req.headers.emplace("Host", host_); - } else { - req.headers.emplace("Host", host_and_port_); - } - } - } - - if (!req.has_header("Accept")) { req.headers.emplace("Accept", "*/*"); } - -#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT - if (!req.has_header("User-Agent")) { - auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION; - req.headers.emplace("User-Agent", agent); - } -#endif - - if (req.body.empty()) { - if (req.content_provider_) { - if (!req.is_chunked_content_provider_) { - if (!req.has_header("Content-Length")) { - auto length = std::to_string(req.content_length_); - req.headers.emplace("Content-Length", length); - } - } - } else { - if (req.method == "POST" || req.method == "PUT" || - req.method == "PATCH") { - req.headers.emplace("Content-Length", "0"); - } - } - } else { - if (!req.has_header("Content-Type")) { - req.headers.emplace("Content-Type", "text/plain"); - } - - if (!req.has_header("Content-Length")) { - auto length = std::to_string(req.body.size()); - req.headers.emplace("Content-Length", length); - } - } - - if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) { - if (!req.has_header("Authorization")) { - req.headers.insert(make_basic_authentication_header( - basic_auth_username_, basic_auth_password_, false)); - } - } - - if (!proxy_basic_auth_username_.empty() && - !proxy_basic_auth_password_.empty()) { - if (!req.has_header("Proxy-Authorization")) { - req.headers.insert(make_basic_authentication_header( - proxy_basic_auth_username_, proxy_basic_auth_password_, true)); - } - } - - if (!bearer_token_auth_token_.empty()) { - if (!req.has_header("Authorization")) { - req.headers.insert(make_bearer_token_authentication_header( - bearer_token_auth_token_, false)); - } - } - - if (!proxy_bearer_token_auth_token_.empty()) { - if (!req.has_header("Proxy-Authorization")) { - req.headers.insert(make_bearer_token_authentication_header( - proxy_bearer_token_auth_token_, true)); - } - } - - // Request line and headers - { - detail::BufferStream bstrm; - - const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path; - bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str()); - - detail::write_headers(bstrm, req.headers); - - // Flush buffer - auto &data = bstrm.get_buffer(); - if (!detail::write_data(strm, data.data(), data.size())) { - error = Error::Write; - return false; - } - } - - // Body - if (req.body.empty()) { - return write_content_with_provider(strm, req, error); - } - - if (!detail::write_data(strm, req.body.data(), req.body.size())) { - error = Error::Write; - return false; - } - - return true; -} - -inline std::unique_ptr ClientImpl::send_with_content_provider( - Request &req, const char *body, size_t content_length, - ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type, Error &error) { - if (!content_type.empty()) { - req.headers.emplace("Content-Type", content_type); - } - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_) { req.headers.emplace("Content-Encoding", "gzip"); } -#endif - -#ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_ && !content_provider_without_length) { - // TODO: Brotli support - detail::gzip_compressor compressor; - - if (content_provider) { - auto ok = true; - size_t offset = 0; - DataSink data_sink; - - data_sink.write = [&](const char *data, size_t data_len) -> bool { - if (ok) { - auto last = offset + data_len == content_length; - - auto ret = compressor.compress( - data, data_len, last, - [&](const char *compressed_data, size_t compressed_data_len) { - req.body.append(compressed_data, compressed_data_len); - return true; - }); - - if (ret) { - offset += data_len; - } else { - ok = false; - } - } - return ok; - }; - - while (ok && offset < content_length) { - if (!content_provider(offset, content_length - offset, data_sink)) { - error = Error::Canceled; - return nullptr; - } - } - } else { - if (!compressor.compress(body, content_length, true, - [&](const char *data, size_t data_len) { - req.body.append(data, data_len); - return true; - })) { - error = Error::Compression; - return nullptr; - } - } - } else -#endif - { - if (content_provider) { - req.content_length_ = content_length; - req.content_provider_ = std::move(content_provider); - req.is_chunked_content_provider_ = false; - } else if (content_provider_without_length) { - req.content_length_ = 0; - req.content_provider_ = detail::ContentProviderAdapter( - std::move(content_provider_without_length)); - req.is_chunked_content_provider_ = true; - req.headers.emplace("Transfer-Encoding", "chunked"); - } else { - req.body.assign(body, content_length); - ; - } - } - - auto res = detail::make_unique(); - return send(req, *res, error) ? std::move(res) : nullptr; -} - -inline Result ClientImpl::send_with_content_provider( - const std::string &method, const std::string &path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, - ContentProviderWithoutLength content_provider_without_length, - const std::string &content_type) { - Request req; - req.method = method; - req.headers = headers; - req.path = path; - - auto error = Error::Success; - - auto res = send_with_content_provider( - req, body, content_length, std::move(content_provider), - std::move(content_provider_without_length), content_type, error); - - return Result{std::move(res), error, std::move(req.headers)}; -} - -inline std::string -ClientImpl::adjust_host_string(const std::string &host) const { - if (host.find(':') != std::string::npos) { return "[" + host + "]"; } - return host; -} - -inline bool ClientImpl::process_request(Stream &strm, Request &req, - Response &res, bool close_connection, - Error &error) { - // Send request - if (!write_request(strm, req, close_connection, error)) { return false; } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if (is_ssl()) { - auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1; - if (!is_proxy_enabled) { - char buf[1]; - if (SSL_peek(socket_.ssl, buf, 1) == 0 && - SSL_get_error(socket_.ssl, 0) == SSL_ERROR_ZERO_RETURN) { - error = Error::SSLPeerCouldBeClosed_; - return false; - } - } - } -#endif - - // Receive response and headers - if (!read_response_line(strm, req, res) || - !detail::read_headers(strm, res.headers)) { - error = Error::Read; - return false; - } - - // Body - if ((res.status != 204) && req.method != "HEAD" && req.method != "CONNECT") { - auto redirect = 300 < res.status && res.status < 400 && follow_location_; - - if (req.response_handler && !redirect) { - if (!req.response_handler(res)) { - error = Error::Canceled; - return false; - } - } - - auto out = - req.content_receiver - ? static_cast( - [&](const char *buf, size_t n, uint64_t off, uint64_t len) { - if (redirect) { return true; } - auto ret = req.content_receiver(buf, n, off, len); - if (!ret) { error = Error::Canceled; } - return ret; - }) - : static_cast( - [&](const char *buf, size_t n, uint64_t /*off*/, - uint64_t /*len*/) { - if (res.body.size() + n > res.body.max_size()) { - return false; - } - res.body.append(buf, n); - return true; - }); - - auto progress = [&](uint64_t current, uint64_t total) { - if (!req.progress || redirect) { return true; } - auto ret = req.progress(current, total); - if (!ret) { error = Error::Canceled; } - return ret; - }; - - int dummy_status; - if (!detail::read_content(strm, res, (std::numeric_limits::max)(), - dummy_status, std::move(progress), std::move(out), - decompress_)) { - if (error != Error::Canceled) { error = Error::Read; } - return false; - } - } - - if (res.get_header_value("Connection") == "close" || - (res.version == "HTTP/1.0" && res.reason != "Connection established")) { - // TODO this requires a not-entirely-obvious chain of calls to be correct - // for this to be safe. Maybe a code refactor (such as moving this out to - // the send function and getting rid of the recursiveness of the mutex) - // could make this more obvious. - - // This is safe to call because process_request is only called by - // handle_request which is only called by send, which locks the request - // mutex during the process. It would be a bug to call it from a different - // thread since it's a thread-safety issue to do these things to the socket - // if another thread is using the socket. - std::lock_guard guard(socket_mutex_); - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); - } - - // Log - if (logger_) { logger_(req, res); } - - return true; -} - -inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider( - const std::string &boundary, const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - size_t cur_item = 0, cur_start = 0; - // cur_item and cur_start are copied to within the std::function and maintain - // state between successive calls - return [&, cur_item, cur_start](size_t offset, - DataSink &sink) mutable -> bool { - if (!offset && items.size()) { - sink.os << detail::serialize_multipart_formdata(items, boundary, false); - return true; - } else if (cur_item < provider_items.size()) { - if (!cur_start) { - const auto &begin = detail::serialize_multipart_formdata_item_begin( - provider_items[cur_item], boundary); - offset += begin.size(); - cur_start = offset; - sink.os << begin; - } - - DataSink cur_sink; - bool has_data = true; - cur_sink.write = sink.write; - cur_sink.done = [&]() { has_data = false; }; - - if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) - return false; - - if (!has_data) { - sink.os << detail::serialize_multipart_formdata_item_end(); - cur_item++; - cur_start = 0; - } - return true; - } else { - sink.os << detail::serialize_multipart_formdata_finish(boundary); - sink.done(); - return true; - } - }; -} - -inline bool -ClientImpl::process_socket(const Socket &socket, - std::function callback) { - return detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, std::move(callback)); -} - -inline bool ClientImpl::is_ssl() const { return false; } - -inline Result ClientImpl::Get(const std::string &path) { - return Get(path, Headers(), Progress()); -} - -inline Result ClientImpl::Get(const std::string &path, Progress progress) { - return Get(path, Headers(), std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers) { - return Get(path, headers, Progress()); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - Progress progress) { - Request req; - req.method = "GET"; - req.path = path; - req.headers = headers; - req.progress = std::move(progress); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Get(const std::string &path, - ContentReceiver content_receiver) { - return Get(path, Headers(), nullptr, std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, Headers(), nullptr, std::move(content_receiver), - std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver) { - return Get(path, headers, nullptr, std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, headers, nullptr, std::move(content_receiver), - std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return Get(path, Headers(), std::move(response_handler), - std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return Get(path, headers, std::move(response_handler), - std::move(content_receiver), nullptr); -} - -inline Result ClientImpl::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, Headers(), std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} - -inline Result ClientImpl::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - Request req; - req.method = "GET"; - req.path = path; - req.headers = headers; - req.response_handler = std::move(response_handler); - req.content_receiver = - [content_receiver](const char *data, size_t data_length, - uint64_t /*offset*/, uint64_t /*total_length*/) { - return content_receiver(data, data_length); - }; - req.progress = std::move(progress); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress) { - if (params.empty()) { return Get(path, headers); } - - std::string path_with_query = append_query_params(path, params); - return Get(path_with_query.c_str(), headers, progress); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ContentReceiver content_receiver, - Progress progress) { - return Get(path, params, headers, nullptr, content_receiver, progress); -} - -inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, - Progress progress) { - if (params.empty()) { - return Get(path, headers, response_handler, content_receiver, progress); - } - - std::string path_with_query = append_query_params(path, params); - return Get(path_with_query.c_str(), headers, response_handler, - content_receiver, progress); -} - -inline Result ClientImpl::Head(const std::string &path) { - return Head(path, Headers()); -} - -inline Result ClientImpl::Head(const std::string &path, - const Headers &headers) { - Request req; - req.method = "HEAD"; - req.headers = headers; - req.path = path; - - return send_(std::move(req)); -} - -inline Result ClientImpl::Post(const std::string &path) { - return Post(path, std::string(), std::string()); -} - -inline Result ClientImpl::Post(const std::string &path, - const Headers &headers) { - return Post(path, headers, nullptr, 0, std::string()); -} - -inline Result ClientImpl::Post(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Post(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, body, content_length, - nullptr, nullptr, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const std::string &body, - const std::string &content_type) { - return Post(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Params ¶ms) { - return Post(path, Headers(), params); -} - -inline Result ClientImpl::Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Post(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Post(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("POST", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const Params ¶ms) { - auto query = detail::params_to_query_str(params); - return Post(path, headers, query, "application/x-www-form-urlencoded"); -} - -inline Result ClientImpl::Post(const std::string &path, - const MultipartFormDataItems &items) { - return Post(path, Headers(), items); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Post(path, headers, body, content_type.c_str()); -} - -inline Result ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - if (!detail::is_multipart_boundary_chars_valid(boundary)) { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } - - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Post(path, headers, body, content_type.c_str()); -} - -inline Result -ClientImpl::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - return send_with_content_provider( - "POST", path, headers, nullptr, 0, nullptr, - get_multipart_content_provider(boundary, items, provider_items), - content_type); -} - -inline Result ClientImpl::Put(const std::string &path) { - return Put(path, std::string(), std::string()); -} - -inline Result ClientImpl::Put(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Put(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, body, content_length, - nullptr, nullptr, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const std::string &body, - const std::string &content_type) { - return Put(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Put(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Put(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Put(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("PUT", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Params ¶ms) { - return Put(path, Headers(), params); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const Params ¶ms) { - auto query = detail::params_to_query_str(params); - return Put(path, headers, query, "application/x-www-form-urlencoded"); -} - -inline Result ClientImpl::Put(const std::string &path, - const MultipartFormDataItems &items) { - return Put(path, Headers(), items); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Put(path, headers, body, content_type); -} - -inline Result ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - if (!detail::is_multipart_boundary_chars_valid(boundary)) { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } - - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - const auto &body = detail::serialize_multipart_formdata(items, boundary); - return Put(path, headers, body, content_type); -} - -inline Result -ClientImpl::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - const auto &boundary = detail::make_multipart_data_boundary(); - const auto &content_type = - detail::serialize_multipart_formdata_get_content_type(boundary); - return send_with_content_provider( - "PUT", path, headers, nullptr, 0, nullptr, - get_multipart_content_provider(boundary, items, provider_items), - content_type); -} -inline Result ClientImpl::Patch(const std::string &path) { - return Patch(path, std::string(), std::string()); -} - -inline Result ClientImpl::Patch(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Patch(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, body, - content_length, nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, - const std::string &body, - const std::string &content_type) { - return Patch(path, Headers(), body, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return Patch(path, Headers(), content_length, std::move(content_provider), - content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return Patch(path, Headers(), std::move(content_provider), content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, nullptr, - content_length, std::move(content_provider), - nullptr, content_type); -} - -inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return send_with_content_provider("PATCH", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); -} - -inline Result ClientImpl::Delete(const std::string &path) { - return Delete(path, Headers(), std::string(), std::string()); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers) { - return Delete(path, headers, std::string(), std::string()); -} - -inline Result ClientImpl::Delete(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return Delete(path, Headers(), body, content_length, content_type); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers, const char *body, - size_t content_length, - const std::string &content_type) { - Request req; - req.method = "DELETE"; - req.headers = headers; - req.path = path; - - if (!content_type.empty()) { - req.headers.emplace("Content-Type", content_type); - } - req.body.assign(body, content_length); - - return send_(std::move(req)); -} - -inline Result ClientImpl::Delete(const std::string &path, - const std::string &body, - const std::string &content_type) { - return Delete(path, Headers(), body.data(), body.size(), content_type); -} - -inline Result ClientImpl::Delete(const std::string &path, - const Headers &headers, - const std::string &body, - const std::string &content_type) { - return Delete(path, headers, body.data(), body.size(), content_type); -} - -inline Result ClientImpl::Options(const std::string &path) { - return Options(path, Headers()); -} - -inline Result ClientImpl::Options(const std::string &path, - const Headers &headers) { - Request req; - req.method = "OPTIONS"; - req.headers = headers; - req.path = path; - - return send_(std::move(req)); -} - -inline size_t ClientImpl::is_socket_open() const { - std::lock_guard guard(socket_mutex_); - return socket_.is_open(); -} - -inline socket_t ClientImpl::socket() const { return socket_.sock; } - -inline void ClientImpl::stop() { - std::lock_guard guard(socket_mutex_); - - // If there is anything ongoing right now, the ONLY thread-safe thing we can - // do is to shutdown_socket, so that threads using this socket suddenly - // discover they can't read/write any more and error out. Everything else - // (closing the socket, shutting ssl down) is unsafe because these actions are - // not thread-safe. - if (socket_requests_in_flight_ > 0) { - shutdown_socket(socket_); - - // Aside from that, we set a flag for the socket to be closed when we're - // done. - socket_should_be_closed_when_request_is_done_ = true; - return; - } - - // Otherwise, still holding the mutex, we can shut everything down ourselves - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); -} - -inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) { - connection_timeout_sec_ = sec; - connection_timeout_usec_ = usec; -} - -inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) { - read_timeout_sec_ = sec; - read_timeout_usec_ = usec; -} - -inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) { - write_timeout_sec_ = sec; - write_timeout_usec_ = usec; -} - -inline void ClientImpl::set_basic_auth(const std::string &username, - const std::string &password) { - basic_auth_username_ = username; - basic_auth_password_ = password; -} - -inline void ClientImpl::set_bearer_token_auth(const std::string &token) { - bearer_token_auth_token_ = token; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_digest_auth(const std::string &username, - const std::string &password) { - digest_auth_username_ = username; - digest_auth_password_ = password; -} -#endif - -inline void ClientImpl::set_keep_alive(bool on) { keep_alive_ = on; } - -inline void ClientImpl::set_follow_location(bool on) { follow_location_ = on; } - -inline void ClientImpl::set_url_encode(bool on) { url_encode_ = on; } - -inline void -ClientImpl::set_hostname_addr_map(std::map addr_map) { - addr_map_ = std::move(addr_map); -} - -inline void ClientImpl::set_default_headers(Headers headers) { - default_headers_ = std::move(headers); -} - -inline void ClientImpl::set_address_family(int family) { - address_family_ = family; -} - -inline void ClientImpl::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; } - -inline void ClientImpl::set_socket_options(SocketOptions socket_options) { - socket_options_ = std::move(socket_options); -} - -inline void ClientImpl::set_compress(bool on) { compress_ = on; } - -inline void ClientImpl::set_decompress(bool on) { decompress_ = on; } - -inline void ClientImpl::set_interface(const std::string &intf) { - interface_ = intf; -} - -inline void ClientImpl::set_proxy(const std::string &host, int port) { - proxy_host_ = host; - proxy_port_ = port; -} - -inline void ClientImpl::set_proxy_basic_auth(const std::string &username, - const std::string &password) { - proxy_basic_auth_username_ = username; - proxy_basic_auth_password_ = password; -} - -inline void ClientImpl::set_proxy_bearer_token_auth(const std::string &token) { - proxy_bearer_token_auth_token_ = token; -} - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_proxy_digest_auth(const std::string &username, - const std::string &password) { - proxy_digest_auth_username_ = username; - proxy_digest_auth_password_ = password; -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path) { - ca_cert_file_path_ = ca_cert_file_path; - ca_cert_dir_path_ = ca_cert_dir_path; -} - -inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (ca_cert_store && ca_cert_store != ca_cert_store_) { - ca_cert_store_ = ca_cert_store; - } -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::enable_server_certificate_verification(bool enabled) { - server_certificate_verification_ = enabled; -} -#endif - -inline void ClientImpl::set_logger(Logger logger) { - logger_ = std::move(logger); -} - -/* - * SSL Implementation - */ -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -namespace detail { - -template -inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex, - U SSL_connect_or_accept, V setup) { - SSL *ssl = nullptr; - { - std::lock_guard guard(ctx_mutex); - ssl = SSL_new(ctx); - } - - if (ssl) { - set_nonblocking(sock, true); - auto bio = BIO_new_socket(static_cast(sock), BIO_NOCLOSE); - BIO_set_nbio(bio, 1); - SSL_set_bio(ssl, bio, bio); - - if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) { - SSL_shutdown(ssl); - { - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); - } - set_nonblocking(sock, false); - return nullptr; - } - BIO_set_nbio(bio, 0); - set_nonblocking(sock, false); - } - - return ssl; -} - -inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, - bool shutdown_gracefully) { - // sometimes we may want to skip this to try to avoid SIGPIPE if we know - // the remote has closed the network connection - // Note that it is not always possible to avoid SIGPIPE, this is merely a - // best-efforts. - if (shutdown_gracefully) { SSL_shutdown(ssl); } - - std::lock_guard guard(ctx_mutex); - SSL_free(ssl); -} - -template -bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl, - U ssl_connect_or_accept, - time_t timeout_sec, - time_t timeout_usec) { - int res = 0; - while ((res = ssl_connect_or_accept(ssl)) != 1) { - auto err = SSL_get_error(ssl, res); - switch (err) { - case SSL_ERROR_WANT_READ: - if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - case SSL_ERROR_WANT_WRITE: - if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; } - break; - default: break; - } - return false; - } - return true; -} - -template -inline bool process_server_socket_ssl( - const std::atomic &svr_sock, SSL *ssl, socket_t sock, - size_t keep_alive_max_count, time_t keep_alive_timeout_sec, - time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - return process_server_socket_core( - svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec, - [&](bool close_connection, bool &connection_closed) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm, close_connection, connection_closed); - }); -} - -template -inline bool -process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec, - time_t read_timeout_usec, time_t write_timeout_sec, - time_t write_timeout_usec, T callback) { - SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec, - write_timeout_sec, write_timeout_usec); - return callback(strm); -} - -class SSLInit { -public: - SSLInit() { - OPENSSL_init_ssl( - OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); - } -}; - -// SSL socket stream implementation -inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl, - time_t read_timeout_sec, - time_t read_timeout_usec, - time_t write_timeout_sec, - time_t write_timeout_usec) - : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec), - read_timeout_usec_(read_timeout_usec), - write_timeout_sec_(write_timeout_sec), - write_timeout_usec_(write_timeout_usec) { - SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); -} - -inline SSLSocketStream::~SSLSocketStream() {} - -inline bool SSLSocketStream::is_readable() const { - return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; -} - -inline bool SSLSocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && - is_socket_alive(sock_); -} - -inline ssize_t SSLSocketStream::read(char *ptr, size_t size) { - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - auto ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret < 0) { - auto err = SSL_get_error(ssl_, ret); - int n = 1000; -#ifdef _WIN32 - while (--n >= 0 && (err == SSL_ERROR_WANT_READ || - (err == SSL_ERROR_SYSCALL && - WSAGetLastError() == WSAETIMEDOUT))) { -#else - while (--n >= 0 && err == SSL_ERROR_WANT_READ) { -#endif - if (SSL_pending(ssl_) > 0) { - return SSL_read(ssl_, ptr, static_cast(size)); - } else if (is_readable()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_read(ssl_, ptr, static_cast(size)); - if (ret >= 0) { return ret; } - err = SSL_get_error(ssl_, ret); - } else { - return -1; - } - } - } - return ret; - } - return -1; -} - -inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { - if (is_writable()) { - auto handle_size = static_cast( - std::min(size, (std::numeric_limits::max)())); - - auto ret = SSL_write(ssl_, ptr, static_cast(handle_size)); - if (ret < 0) { - auto err = SSL_get_error(ssl_, ret); - int n = 1000; -#ifdef _WIN32 - while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE || - (err == SSL_ERROR_SYSCALL && - WSAGetLastError() == WSAETIMEDOUT))) { -#else - while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) { -#endif - if (is_writable()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_write(ssl_, ptr, static_cast(handle_size)); - if (ret >= 0) { return ret; } - err = SSL_get_error(ssl_, ret); - } else { - return -1; - } - } - } - return ret; - } - return -1; -} - -inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - detail::get_remote_ip_and_port(sock_, ip, port); -} - -inline void SSLSocketStream::get_local_ip_and_port(std::string &ip, - int &port) const { - detail::get_local_ip_and_port(sock_, ip, port); -} - -inline socket_t SSLSocketStream::socket() const { return sock_; } - -static SSLInit sslinit_; - -} // namespace detail - -// SSL HTTP server implementation -inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, - const char *client_ca_cert_file_path, - const char *client_ca_cert_dir_path, - const char *private_key_password) { - ctx_ = SSL_CTX_new(TLS_server_method()); - - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - - SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - - // add default password callback before opening encrypted private key - if (private_key_password != nullptr && (private_key_password[0] != '\0')) { - SSL_CTX_set_default_passwd_cb_userdata(ctx_, - (char *)private_key_password); - } - - if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) != - 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_file_path || client_ca_cert_dir_path) { - SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path, - client_ca_cert_dir_path); - - SSL_CTX_set_verify( - ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); - } - } -} - -inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key, - X509_STORE *client_ca_cert_store) { - ctx_ = SSL_CTX_new(TLS_server_method()); - - if (ctx_) { - SSL_CTX_set_options(ctx_, - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - - SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - - if (SSL_CTX_use_certificate(ctx_, cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } else if (client_ca_cert_store) { - SSL_CTX_set_cert_store(ctx_, client_ca_cert_store); - - SSL_CTX_set_verify( - ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); - } - } -} - -inline SSLServer::SSLServer( - const std::function &setup_ssl_ctx_callback) { - ctx_ = SSL_CTX_new(TLS_method()); - if (ctx_) { - if (!setup_ssl_ctx_callback(*ctx_)) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLServer::~SSLServer() { - if (ctx_) { SSL_CTX_free(ctx_); } -} - -inline bool SSLServer::is_valid() const { return ctx_; } - -inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; } - -inline bool SSLServer::process_and_close_socket(socket_t sock) { - auto ssl = detail::ssl_new( - sock, ctx_, ctx_mutex_, - [&](SSL *ssl2) { - return detail::ssl_connect_or_accept_nonblocking( - sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_); - }, - [](SSL * /*ssl2*/) { return true; }); - - auto ret = false; - if (ssl) { - ret = detail::process_server_socket_ssl( - svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, - [this, ssl](Stream &strm, bool close_connection, - bool &connection_closed) { - return process_request(strm, close_connection, connection_closed, - [&](Request &req) { req.ssl = ssl; }); - }); - - // Shutdown gracefully if the result seemed successful, non-gracefully if - // the connection appeared to be closed. - const bool shutdown_gracefully = ret; - detail::ssl_delete(ctx_mutex_, ssl, shutdown_gracefully); - } - - detail::shutdown_socket(sock); - detail::close_socket(sock); - return ret; -} - -// SSL HTTP client implementation -inline SSLClient::SSLClient(const std::string &host) - : SSLClient(host, 443, std::string(), std::string()) {} - -inline SSLClient::SSLClient(const std::string &host, int port) - : SSLClient(host, port, std::string(), std::string()) {} - -inline SSLClient::SSLClient(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : ClientImpl(host, port, client_cert_path, client_key_path) { - ctx_ = SSL_CTX_new(TLS_client_method()); - - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); - }); - - if (!client_cert_path.empty() && !client_key_path.empty()) { - if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(), - SSL_FILETYPE_PEM) != 1 || - SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(), - SSL_FILETYPE_PEM) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLClient::SSLClient(const std::string &host, int port, - X509 *client_cert, EVP_PKEY *client_key) - : ClientImpl(host, port) { - ctx_ = SSL_CTX_new(TLS_client_method()); - - detail::split(&host_[0], &host_[host_.size()], '.', - [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); - }); - - if (client_cert != nullptr && client_key != nullptr) { - if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 || - SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) { - SSL_CTX_free(ctx_); - ctx_ = nullptr; - } - } -} - -inline SSLClient::~SSLClient() { - if (ctx_) { SSL_CTX_free(ctx_); } - // Make sure to shut down SSL since shutdown_ssl will resolve to the - // base function rather than the derived function once we get to the - // base class destructor, and won't free the SSL (causing a leak). - shutdown_ssl_impl(socket_, true); -} - -inline bool SSLClient::is_valid() const { return ctx_; } - -inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (ca_cert_store) { - if (ctx_) { - if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) { - // Free memory allocated for old cert and use new store `ca_cert_store` - SSL_CTX_set_cert_store(ctx_, ca_cert_store); - } - } else { - X509_STORE_free(ca_cert_store); - } - } -} - -inline long SSLClient::get_openssl_verify_result() const { - return verify_result_; -} - -inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; } - -inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) { - return is_valid() && ClientImpl::create_and_connect_socket(socket, error); -} - -// Assumes that socket_mutex_ is locked and that there are no requests in flight -inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, - bool &success, Error &error) { - success = true; - Response res2; - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req2; - req2.method = "CONNECT"; - req2.path = host_and_port_; - return process_request(strm, req2, res2, false, error); - })) { - // Thread-safe to close everything because we are assuming there are no - // requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } - - if (res2.status == 407) { - if (!proxy_digest_auth_username_.empty() && - !proxy_digest_auth_password_.empty()) { - std::map auth; - if (detail::parse_www_authenticate(res2, auth, true)) { - Response res3; - if (!detail::process_client_socket( - socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { - Request req3; - req3.method = "CONNECT"; - req3.path = host_and_port_; - req3.headers.insert(detail::make_digest_authentication_header( - req3, auth, 1, detail::random_string(10), - proxy_digest_auth_username_, proxy_digest_auth_password_, - true)); - return process_request(strm, req3, res3, false, error); - })) { - // Thread-safe to close everything because we are assuming there are - // no requests in flight - shutdown_ssl(socket, true); - shutdown_socket(socket); - close_socket(socket); - success = false; - return false; - } - } - } else { - res = res2; - return false; - } - } - - return true; -} - -inline bool SSLClient::load_certs() { - bool ret = true; - - std::call_once(initialize_cert_, [&]() { - std::lock_guard guard(ctx_mutex_); - if (!ca_cert_file_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(), - nullptr)) { - ret = false; - } - } else if (!ca_cert_dir_path_.empty()) { - if (!SSL_CTX_load_verify_locations(ctx_, nullptr, - ca_cert_dir_path_.c_str())) { - ret = false; - } - } else { - auto loaded = false; -#ifdef _WIN32 - loaded = - detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); -#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) -#if TARGET_OS_OSX - loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_)); -#endif // TARGET_OS_OSX -#endif // _WIN32 - if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); } - } - }); - - return ret; -} - -inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { - auto ssl = detail::ssl_new( - socket.sock, ctx_, ctx_mutex_, - [&](SSL *ssl2) { - if (server_certificate_verification_) { - if (!load_certs()) { - error = Error::SSLLoadingCerts; - return false; - } - SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr); - } - - if (!detail::ssl_connect_or_accept_nonblocking( - socket.sock, ssl2, SSL_connect, connection_timeout_sec_, - connection_timeout_usec_)) { - error = Error::SSLConnection; - return false; - } - - if (server_certificate_verification_) { - verify_result_ = SSL_get_verify_result(ssl2); - - if (verify_result_ != X509_V_OK) { - error = Error::SSLServerVerification; - return false; - } - - auto server_cert = SSL_get1_peer_certificate(ssl2); - - if (server_cert == nullptr) { - error = Error::SSLServerVerification; - return false; - } - - if (!verify_host(server_cert)) { - X509_free(server_cert); - error = Error::SSLServerVerification; - return false; - } - X509_free(server_cert); - } - - return true; - }, - [&](SSL *ssl2) { - SSL_set_tlsext_host_name(ssl2, host_.c_str()); - return true; - }); - - if (ssl) { - socket.ssl = ssl; - return true; - } - - shutdown_socket(socket); - close_socket(socket); - return false; -} - -inline void SSLClient::shutdown_ssl(Socket &socket, bool shutdown_gracefully) { - shutdown_ssl_impl(socket, shutdown_gracefully); -} - -inline void SSLClient::shutdown_ssl_impl(Socket &socket, - bool shutdown_gracefully) { - if (socket.sock == INVALID_SOCKET) { - assert(socket.ssl == nullptr); - return; - } - if (socket.ssl) { - detail::ssl_delete(ctx_mutex_, socket.ssl, shutdown_gracefully); - socket.ssl = nullptr; - } - assert(socket.ssl == nullptr); -} - -inline bool -SSLClient::process_socket(const Socket &socket, - std::function callback) { - assert(socket.ssl); - return detail::process_client_socket_ssl( - socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_, - write_timeout_sec_, write_timeout_usec_, std::move(callback)); -} - -inline bool SSLClient::is_ssl() const { return true; } - -inline bool SSLClient::verify_host(X509 *server_cert) const { - /* Quote from RFC2818 section 3.1 "Server Identity" - - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. - - Matching is performed using the matching rules specified by - [RFC2459]. If more than one identity of a given type is present in - the certificate (e.g., more than one dNSName name, a match in any one - of the set is considered acceptable.) Names may contain the wildcard - character * which is considered to match any single domain name - component or component fragment. E.g., *.a.com matches foo.a.com but - not bar.foo.a.com. f*.com matches foo.com but not bar.com. - - In some cases, the URI is specified as an IP address rather than a - hostname. In this case, the iPAddress subjectAltName must be present - in the certificate and must exactly match the IP in the URI. - - */ - return verify_host_with_subject_alt_name(server_cert) || - verify_host_with_common_name(server_cert); -} - -inline bool -SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { - auto ret = false; - - auto type = GEN_DNS; - - struct in6_addr addr6; - struct in_addr addr; - size_t addr_len = 0; - -#ifndef __MINGW32__ - if (inet_pton(AF_INET6, host_.c_str(), &addr6)) { - type = GEN_IPADD; - addr_len = sizeof(struct in6_addr); - } else if (inet_pton(AF_INET, host_.c_str(), &addr)) { - type = GEN_IPADD; - addr_len = sizeof(struct in_addr); - } -#endif - - auto alt_names = static_cast( - X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); - - if (alt_names) { - auto dsn_matched = false; - auto ip_matched = false; - - auto count = sk_GENERAL_NAME_num(alt_names); - - for (decltype(count) i = 0; i < count && !dsn_matched; i++) { - auto val = sk_GENERAL_NAME_value(alt_names, i); - if (val->type == type) { - auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); - auto name_len = (size_t)ASN1_STRING_length(val->d.ia5); - - switch (type) { - case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; - - case GEN_IPADD: - if (!memcmp(&addr6, name, addr_len) || - !memcmp(&addr, name, addr_len)) { - ip_matched = true; - } - break; - } - } - } - - if (dsn_matched || ip_matched) { ret = true; } - } - - GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)alt_names); - return ret; -} - -inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const { - const auto subject_name = X509_get_subject_name(server_cert); - - if (subject_name != nullptr) { - char name[BUFSIZ]; - auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, - name, sizeof(name)); - - if (name_len != -1) { - return check_host_name(name, static_cast(name_len)); - } - } - - return false; -} - -inline bool SSLClient::check_host_name(const char *pattern, - size_t pattern_len) const { - if (host_.size() == pattern_len && host_ == pattern) { return true; } - - // Wildcard match - // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484 - std::vector pattern_components; - detail::split(&pattern[0], &pattern[pattern_len], '.', - [&](const char *b, const char *e) { - pattern_components.emplace_back(std::string(b, e)); - }); - - if (host_components_.size() != pattern_components.size()) { return false; } - - auto itr = pattern_components.begin(); - for (const auto &h : host_components_) { - auto &p = *itr; - if (p != h && p != "*") { - auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' && - !p.compare(0, p.size() - 1, h)); - if (!partial_match) { return false; } - } - ++itr; - } - - return true; -} -#endif - -// Universal client implementation -inline Client::Client(const std::string &scheme_host_port) - : Client(scheme_host_port, std::string(), std::string()) {} - -inline Client::Client(const std::string &scheme_host_port, - const std::string &client_cert_path, - const std::string &client_key_path) { - const static std::regex re( - R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)"); - - std::smatch m; - if (std::regex_match(scheme_host_port, m, re)) { - auto scheme = m[1].str(); - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if (!scheme.empty() && (scheme != "http" && scheme != "https")) { -#else - if (!scheme.empty() && scheme != "http") { -#endif -#ifndef CPPHTTPLIB_NO_EXCEPTIONS - std::string msg = "'" + scheme + "' scheme is not supported."; - throw std::invalid_argument(msg); -#endif - return; - } - - auto is_ssl = scheme == "https"; - - auto host = m[2].str(); - if (host.empty()) { host = m[3].str(); } - - auto port_str = m[4].str(); - auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80); - - if (is_ssl) { -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT - cli_ = detail::make_unique(host, port, client_cert_path, - client_key_path); - is_ssl_ = is_ssl; -#endif - } else { - cli_ = detail::make_unique(host, port, client_cert_path, - client_key_path); - } - } else { - cli_ = detail::make_unique(scheme_host_port, 80, - client_cert_path, client_key_path); - } -} - -inline Client::Client(const std::string &host, int port) - : cli_(detail::make_unique(host, port)) {} - -inline Client::Client(const std::string &host, int port, - const std::string &client_cert_path, - const std::string &client_key_path) - : cli_(detail::make_unique(host, port, client_cert_path, - client_key_path)) {} - -inline Client::~Client() {} - -inline bool Client::is_valid() const { - return cli_ != nullptr && cli_->is_valid(); -} - -inline Result Client::Get(const std::string &path) { return cli_->Get(path); } -inline Result Client::Get(const std::string &path, const Headers &headers) { - return cli_->Get(path, headers); -} -inline Result Client::Get(const std::string &path, Progress progress) { - return cli_->Get(path, std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - Progress progress) { - return cli_->Get(path, headers, std::move(progress)); -} -inline Result Client::Get(const std::string &path, - ContentReceiver content_receiver) { - return cli_->Get(path, std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver) { - return cli_->Get(path, headers, std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, headers, std::move(content_receiver), - std::move(progress)); -} -inline Result Client::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return cli_->Get(path, std::move(response_handler), - std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver) { - return cli_->Get(path, headers, std::move(response_handler), - std::move(content_receiver)); -} -inline Result Client::Get(const std::string &path, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, headers, std::move(response_handler), - std::move(content_receiver), std::move(progress)); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, Progress progress) { - return cli_->Get(path, params, headers, progress); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, content_receiver, progress); -} -inline Result Client::Get(const std::string &path, const Params ¶ms, - const Headers &headers, - ResponseHandler response_handler, - ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, response_handler, content_receiver, - progress); -} - -inline Result Client::Head(const std::string &path) { return cli_->Head(path); } -inline Result Client::Head(const std::string &path, const Headers &headers) { - return cli_->Head(path, headers); -} - -inline Result Client::Post(const std::string &path) { return cli_->Post(path); } -inline Result Client::Post(const std::string &path, const Headers &headers) { - return cli_->Post(path, headers); -} -inline Result Client::Post(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Post(path, body, content_length, content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Post(path, headers, body, content_length, content_type); -} -inline Result Client::Post(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Post(path, body, content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Post(path, headers, body, content_type); -} -inline Result Client::Post(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Post(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Post(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Post(path, std::move(content_provider), content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Post(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Post(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Post(const std::string &path, const Params ¶ms) { - return cli_->Post(path, params); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const Params ¶ms) { - return cli_->Post(path, headers, params); -} -inline Result Client::Post(const std::string &path, - const MultipartFormDataItems &items) { - return cli_->Post(path, items); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - return cli_->Post(path, headers, items); -} -inline Result Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - return cli_->Post(path, headers, items, boundary); -} -inline Result -Client::Post(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - return cli_->Post(path, headers, items, provider_items); -} -inline Result Client::Put(const std::string &path) { return cli_->Put(path); } -inline Result Client::Put(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Put(path, body, content_length, content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Put(path, headers, body, content_length, content_type); -} -inline Result Client::Put(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Put(path, body, content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Put(path, headers, body, content_type); -} -inline Result Client::Put(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Put(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Put(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Put(path, std::move(content_provider), content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Put(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Put(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Put(const std::string &path, const Params ¶ms) { - return cli_->Put(path, params); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const Params ¶ms) { - return cli_->Put(path, headers, params); -} -inline Result Client::Put(const std::string &path, - const MultipartFormDataItems &items) { - return cli_->Put(path, items); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items) { - return cli_->Put(path, headers, items); -} -inline Result Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const std::string &boundary) { - return cli_->Put(path, headers, items, boundary); -} -inline Result -Client::Put(const std::string &path, const Headers &headers, - const MultipartFormDataItems &items, - const MultipartFormDataProviderItems &provider_items) { - return cli_->Put(path, headers, items, provider_items); -} -inline Result Client::Patch(const std::string &path) { - return cli_->Patch(path); -} -inline Result Client::Patch(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Patch(path, body, content_length, content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Patch(path, headers, body, content_length, content_type); -} -inline Result Client::Patch(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Patch(path, body, content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Patch(path, headers, body, content_type); -} -inline Result Client::Patch(const std::string &path, size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Patch(path, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Patch(const std::string &path, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Patch(path, std::move(content_provider), content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - size_t content_length, - ContentProvider content_provider, - const std::string &content_type) { - return cli_->Patch(path, headers, content_length, std::move(content_provider), - content_type); -} -inline Result Client::Patch(const std::string &path, const Headers &headers, - ContentProviderWithoutLength content_provider, - const std::string &content_type) { - return cli_->Patch(path, headers, std::move(content_provider), content_type); -} -inline Result Client::Delete(const std::string &path) { - return cli_->Delete(path); -} -inline Result Client::Delete(const std::string &path, const Headers &headers) { - return cli_->Delete(path, headers); -} -inline Result Client::Delete(const std::string &path, const char *body, - size_t content_length, - const std::string &content_type) { - return cli_->Delete(path, body, content_length, content_type); -} -inline Result Client::Delete(const std::string &path, const Headers &headers, - const char *body, size_t content_length, - const std::string &content_type) { - return cli_->Delete(path, headers, body, content_length, content_type); -} -inline Result Client::Delete(const std::string &path, const std::string &body, - const std::string &content_type) { - return cli_->Delete(path, body, content_type); -} -inline Result Client::Delete(const std::string &path, const Headers &headers, - const std::string &body, - const std::string &content_type) { - return cli_->Delete(path, headers, body, content_type); -} -inline Result Client::Options(const std::string &path) { - return cli_->Options(path); -} -inline Result Client::Options(const std::string &path, const Headers &headers) { - return cli_->Options(path, headers); -} - -inline bool Client::send(Request &req, Response &res, Error &error) { - return cli_->send(req, res, error); -} - -inline Result Client::send(const Request &req) { return cli_->send(req); } - -inline size_t Client::is_socket_open() const { return cli_->is_socket_open(); } - -inline socket_t Client::socket() const { return cli_->socket(); } - -inline void Client::stop() { cli_->stop(); } - -inline void -Client::set_hostname_addr_map(std::map addr_map) { - cli_->set_hostname_addr_map(std::move(addr_map)); -} - -inline void Client::set_default_headers(Headers headers) { - cli_->set_default_headers(std::move(headers)); -} - -inline void Client::set_address_family(int family) { - cli_->set_address_family(family); -} - -inline void Client::set_tcp_nodelay(bool on) { cli_->set_tcp_nodelay(on); } - -inline void Client::set_socket_options(SocketOptions socket_options) { - cli_->set_socket_options(std::move(socket_options)); -} - -inline void Client::set_connection_timeout(time_t sec, time_t usec) { - cli_->set_connection_timeout(sec, usec); -} - -inline void Client::set_read_timeout(time_t sec, time_t usec) { - cli_->set_read_timeout(sec, usec); -} - -inline void Client::set_write_timeout(time_t sec, time_t usec) { - cli_->set_write_timeout(sec, usec); -} - -inline void Client::set_basic_auth(const std::string &username, - const std::string &password) { - cli_->set_basic_auth(username, password); -} -inline void Client::set_bearer_token_auth(const std::string &token) { - cli_->set_bearer_token_auth(token); -} -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_digest_auth(const std::string &username, - const std::string &password) { - cli_->set_digest_auth(username, password); -} -#endif - -inline void Client::set_keep_alive(bool on) { cli_->set_keep_alive(on); } -inline void Client::set_follow_location(bool on) { - cli_->set_follow_location(on); -} - -inline void Client::set_url_encode(bool on) { cli_->set_url_encode(on); } - -inline void Client::set_compress(bool on) { cli_->set_compress(on); } - -inline void Client::set_decompress(bool on) { cli_->set_decompress(on); } - -inline void Client::set_interface(const std::string &intf) { - cli_->set_interface(intf); -} - -inline void Client::set_proxy(const std::string &host, int port) { - cli_->set_proxy(host, port); -} -inline void Client::set_proxy_basic_auth(const std::string &username, - const std::string &password) { - cli_->set_proxy_basic_auth(username, password); -} -inline void Client::set_proxy_bearer_token_auth(const std::string &token) { - cli_->set_proxy_bearer_token_auth(token); -} -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_proxy_digest_auth(const std::string &username, - const std::string &password) { - cli_->set_proxy_digest_auth(username, password); -} -#endif - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::enable_server_certificate_verification(bool enabled) { - cli_->enable_server_certificate_verification(enabled); -} -#endif - -inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); } - -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path, - const std::string &ca_cert_dir_path) { - cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path); -} - -inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { - if (is_ssl_) { - static_cast(*cli_).set_ca_cert_store(ca_cert_store); - } else { - cli_->set_ca_cert_store(ca_cert_store); - } -} - -inline long Client::get_openssl_verify_result() const { - if (is_ssl_) { - return static_cast(*cli_).get_openssl_verify_result(); - } - return -1; // NOTE: -1 doesn't match any of X509_V_ERR_??? -} - -inline SSL_CTX *Client::ssl_context() const { - if (is_ssl_) { return static_cast(*cli_).ssl_context(); } - return nullptr; -} -#endif - -// ---------------------------------------------------------------------------- - -} // namespace httplib - -#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL) -#undef poll -#endif - -#endif // CPPHTTPLIB_HTTPLIB_H diff --git a/ollama/llm/ext_server/json.hpp b/ollama/llm/ext_server/json.hpp deleted file mode 100755 index ea945f3..0000000 --- a/ollama/llm/ext_server/json.hpp +++ /dev/null @@ -1,24596 +0,0 @@ -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - -/****************************************************************************\ - * Note on documentation: The source files contain links to the online * - * documentation of the public API at https://json.nlohmann.me. This URL * - * contains the most recent documentation and should also be applicable to * - * previous versions; documentation for deprecated functions is not * - * removed, but marked deprecated. See "Generate documentation" section in * - * file docs/README.md. * -\****************************************************************************/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#ifndef JSON_NO_IO - #include // istream, ostream -#endif // JSON_NO_IO -#include // random_access_iterator_tag -#include // unique_ptr -#include // accumulate -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// This file contains all macro definitions affecting or depending on the ABI - -#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 - #warning "Already included a different version of the library!" - #endif - #endif -#endif - -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) - -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - -#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 -#endif - -#if JSON_DIAGNOSTICS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag -#else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS -#endif - -#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp -#else - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 -#endif - -// Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) - -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) - -// Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) - -#if NLOHMANN_JSON_NAMESPACE_NO_VERSION -#define NLOHMANN_JSON_NAMESPACE_VERSION -#else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) -#endif - -// Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) - -#ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ - { -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann -#endif - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // nullptr_t -#include // exception -#include // runtime_error -#include // to_string -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // declval, pair -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -// https://en.cppreference.com/w/cpp/experimental/is_detected -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson -// SPDX-License-Identifier: MIT - -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 15 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #undef JSON_HEDLEY_MCST_LCC_VERSION -#endif -#if defined(__LCC__) && defined(__LCC_MINOR__) - #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) - #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_CRAY_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) && \ - !defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if \ - defined(__has_attribute) && \ - ( \ - (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ - ) -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions (except those affecting ABI) -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// #include - - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -// if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 -#endif - -#ifdef __has_include - #if __has_include() - #include - #endif -#endif - -#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) - #ifdef JSON_HAS_CPP_17 - #if defined(__cpp_lib_filesystem) - #define JSON_HAS_FILESYSTEM 1 - #elif defined(__cpp_lib_experimental_filesystem) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif !defined(__has_include) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #endif - - // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ - #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__clang_major__) && __clang_major__ < 7 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1914 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before iOS 13 - #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before macOS Catalina - #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - #endif -#endif - -#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_FILESYSTEM - #define JSON_HAS_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_THREE_WAY_COMPARISON - #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ - && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L - #define JSON_HAS_THREE_WAY_COMPARISON 1 - #else - #define JSON_HAS_THREE_WAY_COMPARISON 0 - #endif -#endif - -#ifndef JSON_HAS_RANGES - // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error - #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 - #define JSON_HAS_RANGES 0 - #elif defined(__cpp_lib_ranges) - #define JSON_HAS_RANGES 1 - #else - #define JSON_HAS_RANGES 0 - #endif -#endif - -#ifdef JSON_HAS_CPP_17 - #define JSON_INLINE_VARIABLE inline -#else - #define JSON_INLINE_VARIABLE -#endif - -#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) - #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] -#else - #define JSON_NO_UNIQUE_ADDRESS -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -#endif - -// allow disabling exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow overriding assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_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, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); -#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - - -// inspired from https://stackoverflow.com/a/26745591 -// allows to call any std function as if (e.g. with begin): -// using std::begin; begin(x); -// -// it allows using the detected idiom to retrieve the return type -// of such an expression -#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ - namespace detail { \ - using std::std_name; \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - } \ - \ - namespace detail2 { \ - struct std_name##_tag \ - { \ - }; \ - \ - template \ - std_name##_tag std_name(T&&...); \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - \ - template \ - struct would_call_std_##std_name \ - { \ - static constexpr auto const value = ::nlohmann::detail:: \ - is_detected_exact::value; \ - }; \ - } /* namespace detail2 */ \ - \ - template \ - struct would_call_std_##std_name : detail2::would_call_std_##std_name \ - { \ - } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - -#ifndef JSON_DISABLE_ENUM_SERIALIZATION - #define JSON_DISABLE_ENUM_SERIALIZATION 0 -#endif - -#ifndef JSON_USE_GLOBAL_UDLS - #define JSON_USE_GLOBAL_UDLS 1 -#endif - -#if JSON_HAS_THREE_WAY_COMPARISON - #include // partial_ordering -#endif - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -#if JSON_HAS_THREE_WAY_COMPARISON - inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* -#else - inline bool operator<(const value_t lhs, const value_t rhs) noexcept -#endif -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); -#if JSON_HAS_THREE_WAY_COMPARISON - if (l_index < order.size() && r_index < order.size()) - { - return order[l_index] <=> order[r_index]; // *NOPAD* - } - return std::partial_ordering::unordered; -#else - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -#endif -} - -// GCC selects the built-in operator< over an operator rewritten from -// a user-defined spaceship operator -// Clang, MSVC, and ICC select the rewritten candidate -// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) -#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - return std::is_lt(lhs <=> rhs); // *NOPAD* -} -#endif - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/*! -@brief replace all occurrences of a substring by another string - -@param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t -@param[in] f the substring to replace with @a t -@param[in] t the string to replace @a f - -@pre The search string @a f must not be empty. **This precondition is -enforced with an assertion.** - -@since version 2.0.0 -*/ -template -inline void replace_substring(StringType& s, const StringType& f, - const StringType& t) -{ - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -static void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -inline constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval -#include // tuple - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // random_access_iterator_tag - -// #include - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); - -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); - -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.2 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann -// SPDX-License-Identifier: MIT - -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector - - // #include - - - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN - - /*! - @brief default JSONSerializer template argument - - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> - class basic_json; - - /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document - /// @sa https://json.nlohmann.me/api/json_pointer/ - template - class json_pointer; - - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; - - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; - - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; - - NLOHMANN_JSON_NAMESPACE_END - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ - -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -// used by exceptions create() member functions -// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t -// false_type otherwise -template -struct is_basic_json_context : - std::integral_constant < bool, - is_basic_json::type>::type>::value - || std::is_same::value > -{}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -template -using detect_key_compare = typename T::key_compare; - -template -struct has_key_compare : std::integral_constant::value> {}; - -// obtains the actual object key comparator -template -struct actual_object_comparator -{ - using object_t = typename BasicJsonType::object_t; - using object_comparator_t = typename BasicJsonType::default_object_comparator_t; - using type = typename std::conditional < has_key_compare::value, - typename object_t::key_compare, object_comparator_t>::type; -}; - -template -using actual_object_comparator_t = typename actual_object_comparator::type; - -/////////////////// -// is_ functions // -/////////////////// - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B { }; -template -struct conjunction -: std::conditional(B::value), conjunction, B>::type {}; - -// https://en.cppreference.com/w/cpp/types/negation -template struct negation : std::integral_constant < bool, !B::value > { }; - -// Reimplementation of is_constructible and is_default_constructible, due to them being broken for -// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). -// This causes compile errors in e.g. clang 3.5 or gcc 4.9. -template -struct is_default_constructible : std::is_default_constructible {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - - -template -struct is_constructible : std::is_constructible {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -template -struct is_range -{ - private: - using t_ref = typename std::add_lvalue_reference::type; - - using iterator = detected_t; - using sentinel = detected_t; - - // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator - // and https://en.cppreference.com/w/cpp/iterator/sentinel_for - // but reimplementing these would be too much work, as a lot of other concepts are used underneath - static constexpr auto is_iterator_begin = - is_iterator_traits>::value; - - public: - static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; -}; - -template -using iterator_t = enable_if_t::value, result_of_begin())>>; - -template -using range_value_t = value_type_t>>; - -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - is_constructible::value && - is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_constructible_string_type -{ - // launder type through decltype() to fix compilation failure on ICPC -#ifdef __INTEL_COMPILER - using laundered_type = decltype(std::declval()); -#else - using laundered_type = ConstructibleStringType; -#endif - - static constexpr auto value = - conjunction < - is_constructible, - is_detected_exact>::value; -}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < - is_detected::value&& - is_iterator_traits>>::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 - !std::is_same>::value >> -{ - static constexpr bool value = - is_constructible>::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - !is_compatible_string_type::value&& - is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_iterator_traits>>::value&& -is_detected::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 -!std::is_same>::value&& - is_complete_type < - detected_t>::value >> -{ - using value_type = range_value_t; - - static constexpr bool value = - std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, - value_type >::value; -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; - -template -struct is_json_iterator_of : std::false_type {}; - -template -struct is_json_iterator_of : std::true_type {}; - -template -struct is_json_iterator_of : std::true_type -{}; - -// checks if a given type T is a template specialization of Primary -template