From d1f0a9d7b7379460fe4126eda67d5ca391ca2ac9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 19 Jun 2024 11:11:58 +0200 Subject: [PATCH] - --- .env | 4 +- .upsun/config.yaml | 41 +- README.md | 19 +- docker/pgsql/postgres.Dockerfile | 2 +- package-lock.json | 756 ++++++++++++------------------- package.json | 4 +- public/next.svg | 1 - public/vercel.svg | 1 - src/app/actions.ts | 64 +-- vectorize/requirements-mac.txt | 35 -- vectorize/requirements.txt | 38 +- vectorize/vectorize.py | 95 ++-- 12 files changed, 417 insertions(+), 643 deletions(-) delete mode 100644 public/next.svg delete mode 100644 public/vercel.svg delete mode 100644 vectorize/requirements-mac.txt diff --git a/.env b/.env index 153f9d9..086fc74 100644 --- a/.env +++ b/.env @@ -4,4 +4,6 @@ # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" \ No newline at end of file +DATABASE_URL="postgresql://watches:watches@localhost:${FORWARD_DB_PORT:-5432}/watches?schema=public" +EMBEDDING_MODEL=all-minilm +CHAT_MODEL=phi3:mini diff --git a/.upsun/config.yaml b/.upsun/config.yaml index 8242e0c..2df9fcb 100644 --- a/.upsun/config.yaml +++ b/.upsun/config.yaml @@ -6,19 +6,46 @@ services: - vector applications: + ollama: + stack: + - "python@3.12" + - "ollama" + container_profile: BALANCED + relationships: + db: "postgresql:postgresql" + mounts: + "/.ollama": + source: "storage" + source_path: ".ollama" + web: + commands: + start: "OLLAMA_HOST=:$PORT ollama serve" + hooks: + build: | + set -eux + cd vectorize/ + pip install -r requirements.txt + deploy: | + set -eux + set -a + . /app/.env + export OLLAMA_HOST=:$PORT + ollama pull $EMBEDDING_MODEL + ollama pull $CHAT_MODEL + + cd vectorize/ + python vectorize.py + app: stack: - "nodejs@22" - - "python@3.12" relationships: db: "postgresql:postgresql" + ollama: "ollama:http" mounts: "/.npm": source: "storage" source_path: "npm" - "/.cache": - source: "storage" - source_path: "cache" web: commands: start: "npx next start -p $PORT" @@ -28,12 +55,6 @@ applications: npm install npx prisma generate npm run build - cd vectorize/ - pip install -r requirements.txt - post_deploy: | - set -eux - cd vectorize/ - python vectorize.py routes: "https://{default}/": diff --git a/README.md b/README.md index b1f9932..0adfd82 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ The data located in `vectorize/data` is a [dataset from Kaggle](https://www.kaggle.com/datasets/rkiattisak/luxury-watches-price-dataset/data). -This example uses 3 models from HuggingFace: -- `vectorize.py` uses the `sentence-transformers` and run `feature_extractor` with the `all-MiniLM-L6-v2` model locally (CPU). The model is downloaded (88MB) on the first run in the `.cache` folder. The embeddings are then stored in the postgres database. `vectorize.py` also migrates the database schema if it does not exists. +This example uses a local Ollama server: +- `vectorize.py` uses the `all-minilm` model run `feature_extractor` with the `all-MiniLM-L6-v2` model locally (CPU). The model is downloaded (88MB) on the first run in the `~/.cache/huggingface/` folder. The embeddings are then stored in the postgres database. `vectorize.py` also migrates the database schema if it does not exist. - When the user inputs a prompt, the `recommend` action will first run `featureExtraction` on the serverless HuggingFace inference API with the same model `all-MiniLM-L6-v2` to get the embedding. - The `recommend` action then query the database using the vector to get 5 similar watches. - The last step of the action is to query a text generation model on HuggingFace inference API to generate a proper text answer. We are using `mistralai/Mistral-7B-Instruct-v0.2` in this example. @@ -22,15 +22,17 @@ The `openai` branch does the same but relies on the OpenAI API for all the LLM a cd vectorize python3 -m venv venv source ./venv/bin/activate -pip install -r requirements.txt (or requirements-mac.txt) +pip install -r requirements.txt ``` ### Install dependencies and run services ``` -docker-compose up +export FORWARD_DB_PORT=8090 +docker compose up -d cd vectorize/ -DB_PATH=watches DB_HOST=127.0.0.1 DB_USERNAME=watches DB_PASSWORD=watches HUGGINGFACE_TOKEN=hf_****** python3 vectorize.py +source ../.env.local +DB_PORT=$FORWARD_DB_PORT DB_PATH=watches DB_HOST=127.0.0.1 DB_USERNAME=watches DB_PASSWORD=watches python3 vectorize.py cd ../ npm install npm rum dev @@ -40,8 +42,9 @@ npm rum dev ``` upsun project:create -upsun variable:create --name HUGGINGFACE_TOKEN --prefix env: --level project -upsun push +upsun variable:create --name env:EMBEDDING_MODEL --level project --visible-build=true --value=all-minilm +upsun variable:create --name env:CHAT_MODEL --level project --visible-build=true --value=tinyllama:1.1b-chat-v1-q2_K +upsun push --resources-init=manual ``` -The `vectorize.py` script is included in the `deploy` hook meaning that it will be triggered on every deploy. This is for demo purposes. You can run it manually instead to avoid delays in deployments. \ No newline at end of file +The `vectorize.py` script is included in the `deploy` hook meaning that it will be triggered on every deploy. This is for demo purposes. You can run it manually instead to avoid delays in deployments. diff --git a/docker/pgsql/postgres.Dockerfile b/docker/pgsql/postgres.Dockerfile index dbf9a63..38bc157 100644 --- a/docker/pgsql/postgres.Dockerfile +++ b/docker/pgsql/postgres.Dockerfile @@ -1,4 +1,4 @@ -FROM postgres:latest +FROM postgres:16 RUN apt-get update && apt-get install -y \ build-essential \ diff --git a/package-lock.json b/package-lock.json index c64181f..a57a7ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,6 @@ "name": "watches-next", "version": "0.1.0", "dependencies": { - "@ai-sdk/openai": "^0.0.17", - "@huggingface/inference": "^2.7.0", "@prisma/client": "^5.14.0", "@radix-ui/react-slot": "^1.0.2", "ai": "^3.1.17", @@ -17,7 +15,7 @@ "clsx": "^2.1.1", "lucide-react": "^0.379.0", "next": "14.2.3", - "openai": "^4.47.2", + "ollama": "^0.5.2", "prisma": "^5.14.0", "react": "^18", "react-dom": "^18", @@ -38,69 +36,131 @@ "typescript": "^5" } }, - "node_modules/@ai-sdk/openai": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-0.0.17.tgz", - "integrity": "sha512-5Es+u9ICw23FZnRfRQLwn9AxkRcTDxGMFKcZjaLdj8suBeUd3B/CioUTNgXUTvfRCOPhkH/sbLrMyo746LkOAg==", + "node_modules/@ai-sdk/provider": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.10.tgz", + "integrity": "sha512-NzkrtREQpHID1cTqY/C4CI30PVOaXWKYytDR2EcytmFgnP7Z6+CrGIA/YCnNhYAuUm6Nx+nGpRL/Hmyrv7NYzg==", "dependencies": { - "@ai-sdk/provider": "0.0.8", - "@ai-sdk/provider-utils": "0.0.11" + "json-schema": "0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-0.0.15.tgz", + "integrity": "sha512-eTkIaZc/Ud96DYG40lLuKWJvZ2GoW/wT4KH9r1f3wGUhj5wgQN+bzgdI57z60VOEDuMmDVuILVnTLFe0HNT5Iw==", + "dependencies": { + "@ai-sdk/provider": "0.0.10", + "eventsource-parser": "1.1.2", + "nanoid": "3.3.6", + "secure-json-parse": "2.7.0" }, "engines": { "node": ">=18" }, "peerDependencies": { "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } } }, - "node_modules/@ai-sdk/provider": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.8.tgz", - "integrity": "sha512-+gcMvyPUDfDXV9caN3CG5Le0M5K4CjqTdMV1ODg/AosApQiJW9ByN5imJPdI043zVdt+HS9WG+s0j4am7ca4bg==", + "node_modules/@ai-sdk/react": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-0.0.3.tgz", + "integrity": "sha512-P7VAuo4lrO2GTB5vgNN6M7Ws07S4VXryguSE1DaSy2EAnZvxBURau/j0zcVo3FdyCPHwyZesMCyElmcTUuirOA==", "dependencies": { - "json-schema": "0.4.0" + "@ai-sdk/provider-utils": "0.0.15", + "@ai-sdk/ui-utils": "0.0.3", + "swr": "2.2.0" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/@ai-sdk/provider-utils": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-0.0.11.tgz", - "integrity": "sha512-JRDrqL2FGDmLh+a4R5qbS8UrWN9Lt7DpDIY1x6owgXjXkz3Umm1czs1X32VlL0M1dpoSxu4hGBFtXd56+kDzXA==", + "node_modules/@ai-sdk/solid": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/solid/-/solid-0.0.3.tgz", + "integrity": "sha512-arCWuCO/jowIaFRIbczv44rHwGV8oW/ON8Sc3W7gFlparnt7z1umdwcEFo4BXbHxvMNsd9xYv4FFrgSTkULxbQ==", "dependencies": { - "@ai-sdk/provider": "0.0.8", - "eventsource-parser": "1.1.2", - "nanoid": "3.3.6", - "secure-json-parse": "2.7.0" + "@ai-sdk/ui-utils": "0.0.3", + "solid-swr-store": "0.10.7", + "swr-store": "0.10.6" }, "engines": { "node": ">=18" }, "peerDependencies": { - "zod": "^3.0.0" + "solid-js": "^1.7.7" }, "peerDependenciesMeta": { - "zod": { + "solid-js": { "optional": true } } }, - "node_modules/@ai-sdk/provider-utils/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" + "node_modules/@ai-sdk/svelte": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/svelte/-/svelte-0.0.3.tgz", + "integrity": "sha512-Utf5ocrhXOzf/JhpR4w7oZbWEG6OuEHZlH8whCG5qsKPbTDR06OzFPIGdHKjo55KUTNqpTqpcrMZriy3/BG0xQ==", + "dependencies": { + "@ai-sdk/provider-utils": "0.0.15", + "@ai-sdk/ui-utils": "0.0.3", + "sswr": "2.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "svelte": "^3.0.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + } + }, + "node_modules/@ai-sdk/ui-utils": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-0.0.3.tgz", + "integrity": "sha512-V3tF7zh1h4wEORlh8hRE8MI31KiCE/RliXrVNQT9aW3+lAlDNd9nd/sEtGsdioxhJcddqQmPxycVrSOSAFEEzw==", + "dependencies": { + "@ai-sdk/provider-utils": "0.0.15" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=18" + } + }, + "node_modules/@ai-sdk/vue": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/vue/-/vue-0.0.3.tgz", + "integrity": "sha512-HtpFZBCFayn34s68jel6KdFgMa+iC3pNfWVIld/vqgJ4OM1seuY4fVz8+52wEw737FN9hqYvEY+93jORoxgOCg==", + "dependencies": { + "@ai-sdk/ui-utils": "0.0.3", + "swrv": "1.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "vue": "^3.3.4" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } } }, "node_modules/@alloc/quick-lru": { @@ -128,9 +188,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "peer": true, "bin": { "parser": "bin/babel-parser.js" @@ -140,9 +200,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", - "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -166,9 +226,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -206,26 +266,11 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@huggingface/inference": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-2.7.0.tgz", - "integrity": "sha512-u7Fn637Q3f7nUB1tajM4CgzhvoFQkOQr5W5Fm+2wT9ETgGoLBh25BLlYPTJRjAd2WY01s71v0lqAwNvHHCc3mg==", - "dependencies": { - "@huggingface/tasks": "^0.10.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@huggingface/tasks": { - "version": "0.10.9", - "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.10.9.tgz", - "integrity": "sha512-KdGnpw7sTLgr9nUwH6NrMHi/6/yBe5HdeXeKWauajseKZXwyrTYwNYIzMnh8/hE7Qa2UnseAdFMpCqe54vGd4A==" - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", @@ -253,6 +298,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@isaacs/cliui": { @@ -530,9 +576,9 @@ } }, "node_modules/@prisma/client": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.14.0.tgz", - "integrity": "sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.15.1.tgz", + "integrity": "sha512-fmZRGmsUJ9+VwC/AvfP/PwdpD0xAEyPvNsD9/B3+GYpETq9VejVRT3PiqNvl76q1uYYzNZeo8u/LmzzTetHSEg==", "hasInstallScript": true, "engines": { "node": ">=16.13" @@ -547,43 +593,43 @@ } }, "node_modules/@prisma/debug": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", - "integrity": "sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==" + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.15.1.tgz", + "integrity": "sha512-NQjdEplhXEcPvf84ghxExC+LD+iTimbg3sZvA3BhybVQIocBEBxFf9GTHhmRVPmjrWoBaYJBVgEEBXZT27JTbQ==" }, "node_modules/@prisma/engines": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.14.0.tgz", - "integrity": "sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.15.1.tgz", + "integrity": "sha512-1iTRxJEFvpBpEWf2bYiMG6LBBQhX7X+GA5piH+tmPWgc/v+/ElxQf2kjQxby8AErmZqtZkdoKJ7FSRjNjBPE9Q==", "hasInstallScript": true, "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/fetch-engine": "5.14.0", - "@prisma/get-platform": "5.14.0" + "@prisma/debug": "5.15.1", + "@prisma/engines-version": "5.15.1-1.5675a3182f972f1a8f31d16eee6abf4fd54910e3", + "@prisma/fetch-engine": "5.15.1", + "@prisma/get-platform": "5.15.1" } }, "node_modules/@prisma/engines-version": { - "version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48.tgz", - "integrity": "sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==" + "version": "5.15.1-1.5675a3182f972f1a8f31d16eee6abf4fd54910e3", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.15.1-1.5675a3182f972f1a8f31d16eee6abf4fd54910e3.tgz", + "integrity": "sha512-7csphKGCG6n/cN1MkT1mJvQ78Ir18IknlYZ8eyEoLKdQBb0HscR/6TyPmzqrMA7Rz01K1KeXqctwAqxtA/lKQg==" }, "node_modules/@prisma/fetch-engine": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.14.0.tgz", - "integrity": "sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.15.1.tgz", + "integrity": "sha512-mj0wfsJ+mAdDp1ynT2JKxAXa+CoYMT267qF7g2Uv+oaVTI2CMfGWouMARht8T2QLTgl+gpXSFTwIYbcR+oWEtw==", "dependencies": { - "@prisma/debug": "5.14.0", - "@prisma/engines-version": "5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48", - "@prisma/get-platform": "5.14.0" + "@prisma/debug": "5.15.1", + "@prisma/engines-version": "5.15.1-1.5675a3182f972f1a8f31d16eee6abf4fd54910e3", + "@prisma/get-platform": "5.15.1" } }, "node_modules/@prisma/get-platform": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.14.0.tgz", - "integrity": "sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.15.1.tgz", + "integrity": "sha512-oFccp7bYys+ZYkmtYzjR+0cRrGKvSuF+h5QhSkyEsYQ9kzJzQRvuWt2SiHRPt8xOQ4MTmujM+bP5uOexnnAHdQ==", "dependencies": { - "@prisma/debug": "5.14.0" + "@prisma/debug": "5.15.1" } }, "node_modules/@radix-ui/react-compose-refs": { @@ -695,22 +741,14 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "20.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", + "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", + "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -872,13 +910,13 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vue/compiler-core": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", - "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.29.tgz", + "integrity": "sha512-TFKiRkKKsRCKvg/jTSSKK7mYLJEQdUiUfykbG49rubC9SfDyvT2JrzTReopWlz2MxqeLyxh9UZhvxEIBgAhtrg==", "peer": true, "dependencies": { - "@babel/parser": "^7.24.4", - "@vue/shared": "3.4.27", + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.29", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" @@ -891,26 +929,26 @@ "peer": true }, "node_modules/@vue/compiler-dom": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", - "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.29.tgz", + "integrity": "sha512-A6+iZ2fKIEGnfPJejdB7b1FlJzgiD+Y/sxxKwJWg1EbJu6ZPgzaPQQ51ESGNv0CP6jm6Z7/pO6Ia8Ze6IKrX7w==", "peer": true, "dependencies": { - "@vue/compiler-core": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-core": "3.4.29", + "@vue/shared": "3.4.29" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", - "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.29.tgz", + "integrity": "sha512-zygDcEtn8ZimDlrEQyLUovoWgKQic6aEQqRXce2WXBvSeHbEbcAsXyCk9oG33ZkyWH4sl9D3tkYc1idoOkdqZQ==", "peer": true, "dependencies": { - "@babel/parser": "^7.24.4", - "@vue/compiler-core": "3.4.27", - "@vue/compiler-dom": "3.4.27", - "@vue/compiler-ssr": "3.4.27", - "@vue/shared": "3.4.27", + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.29", + "@vue/compiler-dom": "3.4.29", + "@vue/compiler-ssr": "3.4.29", + "@vue/shared": "3.4.29", "estree-walker": "^2.0.2", "magic-string": "^0.30.10", "postcss": "^8.4.38", @@ -924,79 +962,69 @@ "peer": true }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", - "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.29.tgz", + "integrity": "sha512-rFbwCmxJ16tDp3N8XCx5xSQzjhidYjXllvEcqX/lopkoznlNPz3jyy0WGJCyhAaVQK677WWFt3YO/WUEkMMUFQ==", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-dom": "3.4.29", + "@vue/shared": "3.4.29" } }, "node_modules/@vue/reactivity": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", - "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.29.tgz", + "integrity": "sha512-w8+KV+mb1a8ornnGQitnMdLfE0kXmteaxLdccm2XwdFxXst4q/Z7SEboCV5SqJNpZbKFeaRBBJBhW24aJyGINg==", "peer": true, "dependencies": { - "@vue/shared": "3.4.27" + "@vue/shared": "3.4.29" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", - "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.29.tgz", + "integrity": "sha512-s8fmX3YVR/Rk5ig0ic0NuzTNjK2M7iLuVSZyMmCzN/+Mjuqqif1JasCtEtmtoJWF32pAtUjyuT2ljNKNLeOmnQ==", "peer": true, "dependencies": { - "@vue/reactivity": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/reactivity": "3.4.29", + "@vue/shared": "3.4.29" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", - "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.29.tgz", + "integrity": "sha512-gI10atCrtOLf/2MPPMM+dpz3NGulo9ZZR9d1dWo4fYvm+xkfvRrw1ZmJ7mkWtiJVXSsdmPbcK1p5dZzOCKDN0g==", "peer": true, "dependencies": { - "@vue/runtime-core": "3.4.27", - "@vue/shared": "3.4.27", + "@vue/reactivity": "3.4.29", + "@vue/runtime-core": "3.4.29", + "@vue/shared": "3.4.29", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", - "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.29.tgz", + "integrity": "sha512-HMLCmPI2j/k8PVkSBysrA2RxcxC5DgBiCdj7n7H2QtR8bQQPqKAe8qoaxLcInzouBmzwJ+J0x20ygN/B5mYBng==", "peer": true, "dependencies": { - "@vue/compiler-ssr": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-ssr": "3.4.29", + "@vue/shared": "3.4.29" }, "peerDependencies": { - "vue": "3.4.27" + "vue": "3.4.29" } }, "node_modules/@vue/shared": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", - "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.29.tgz", + "integrity": "sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA==", "peer": true }, - "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/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "bin": { "acorn": "bin/acorn" }, @@ -1013,34 +1041,24 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "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/ai": { - "version": "3.1.17", - "resolved": "https://registry.npmjs.org/ai/-/ai-3.1.17.tgz", - "integrity": "sha512-m1J3friKSvF20lV6UT38Zkraoc3ci3nmIcTpxVdFID7lmHc3KiqNjOsunNXHmRGKBZvTGuechYo84iBeieusXg==", - "dependencies": { - "@ai-sdk/provider": "0.0.8", - "@ai-sdk/provider-utils": "0.0.11", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ai/-/ai-3.2.0.tgz", + "integrity": "sha512-1CLnzTNdBoPJs8GDgKa4qEUw9UcYS6tzAL4DtWO1Twt0/DOhtfck9i4JZPuE0mg1e01WeOHG/U4QTDFTdgeuuw==", + "dependencies": { + "@ai-sdk/provider": "0.0.10", + "@ai-sdk/provider-utils": "0.0.15", + "@ai-sdk/react": "0.0.3", + "@ai-sdk/solid": "0.0.3", + "@ai-sdk/svelte": "0.0.3", + "@ai-sdk/ui-utils": "0.0.3", + "@ai-sdk/vue": "0.0.3", "eventsource-parser": "1.1.2", "json-schema": "0.4.0", "jsondiffpatch": "0.6.0", "nanoid": "3.3.6", "secure-json-parse": "2.7.0", - "solid-swr-store": "0.10.7", - "sswr": "2.0.0", - "swr": "2.2.0", - "swr-store": "0.10.6", - "swrv": "1.0.4", + "sswr": "2.1.0", "zod-to-json-schema": "3.22.5" }, "engines": { @@ -1049,9 +1067,7 @@ "peerDependencies": { "openai": "^4.42.0", "react": "^18 || ^19", - "solid-js": "^1.7.7", "svelte": "^3.0.0 || ^4.0.0", - "vue": "^3.3.4", "zod": "^3.0.0" }, "peerDependenciesMeta": { @@ -1061,37 +1077,14 @@ "react": { "optional": true }, - "solid-js": { - "optional": true - }, "svelte": { "optional": true }, - "vue": { - "optional": true - }, "zod": { "optional": true } } }, - "node_modules/ai/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1300,16 +1293,19 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { @@ -1340,11 +1336,6 @@ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, - "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/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -1472,9 +1463,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001625", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", - "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "funding": [ { "type": "opencollective", @@ -1646,17 +1637,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "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/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1780,9 +1760,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -1847,14 +1827,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1925,9 +1897,9 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/enhanced-resolve": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", - "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -2363,16 +2335,16 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz", - "integrity": "sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==", + "version": "7.34.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", + "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", @@ -2549,14 +2521,6 @@ "node": ">=0.10.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/eventsource-parser": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", @@ -2691,9 +2655,9 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -2705,44 +2669,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "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/formdata-node/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/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3100,14 +3026,6 @@ "url": "https://opencollective.com/unified" } }, - "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/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -3641,9 +3559,9 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "bin": { "jiti": "bin/jiti.js" } @@ -4092,9 +4010,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", - "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", @@ -4703,25 +4621,6 @@ "node": ">=8.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/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4767,9 +4666,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "funding": [ { "type": "github", @@ -4865,43 +4764,6 @@ "node": "^10 || ^12 || >=14" } }, - "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/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5042,6 +4904,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ollama": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.5.2.tgz", + "integrity": "sha512-nH9WEU8lGxX2RhTH9TukjwrQBlyoprIh8wIGMfFlprgzzJgAr+MFFmHzCt7BZt4SMFMXVwM2xnKrfshfHkBLyQ==", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5051,32 +4921,6 @@ "wrappy": "1" } }, - "node_modules/openai": { - "version": "4.47.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.47.2.tgz", - "integrity": "sha512-E3Wq9mYdDSLajmcJm9RO/lCegTKrQ7ilAkMbhob4UgGhTjHwIHI+mXNDNPl5+sGIUp2iVUkpoi772FjYa7JlqA==", - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7", - "web-streams-polyfill": "^3.2.1" - }, - "bin": { - "openai": "bin/cli" - } - }, - "node_modules/openai/node_modules/@types/node": { - "version": "18.19.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", - "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5363,9 +5207,9 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { "node": ">=14" }, @@ -5408,6 +5252,23 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5418,12 +5279,12 @@ } }, "node_modules/prisma": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.14.0.tgz", - "integrity": "sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.15.1.tgz", + "integrity": "sha512-pYsUVpTlYvZ6mWvZKDv9rKdUa7tlfSUJY1CVtgb8Had1pHbIm9fr1MBASccr5XnSuCUrjnvKhWNwgSYy6aCajA==", "hasInstallScript": true, "dependencies": { - "@prisma/engines": "5.14.0" + "@prisma/engines": "5.15.1" }, "bin": { "prisma": "build/index.js" @@ -5972,14 +5833,14 @@ } }, "node_modules/sswr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sswr/-/sswr-2.0.0.tgz", - "integrity": "sha512-mV0kkeBHcjcb0M5NqKtKVg/uTIYNlIIniyDfSGrSfxpEdM9C365jK0z55pl9K0xAkNTJi2OAOVFQpgMPUk+V0w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sswr/-/sswr-2.1.0.tgz", + "integrity": "sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==", "dependencies": { "swrev": "^4.0.0" }, "peerDependencies": { - "svelte": "^4.0.0" + "svelte": "^4.0.0 || ^5.0.0-next.0" } }, "node_modules/streamsearch": { @@ -6257,9 +6118,9 @@ } }, "node_modules/svelte": { - "version": "4.2.17", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.17.tgz", - "integrity": "sha512-N7m1YnoXtRf5wya5Gyx3TWuTddI4nAyayyIWFojiWV5IayDYNV5i2mRp/7qNGol4DtxEYxljmrbgp1HM6hUbmQ==", + "version": "4.2.18", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.18.tgz", + "integrity": "sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.1", @@ -6338,9 +6199,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", - "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -6426,11 +6287,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -6479,9 +6335,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/type-check": { "version": "0.4.0", @@ -6611,12 +6467,13 @@ "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==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/unified": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", - "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", @@ -6757,16 +6614,16 @@ } }, "node_modules/vue": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", - "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "version": "3.4.29", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.29.tgz", + "integrity": "sha512-8QUYfRcYzNlYuzKPfge1UWC6nF9ym0lx7mpGVPJYNhddxEf3DD0+kU07NTL0sXuiT2HuJuKr/iEO8WvXvT0RSQ==", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.4.27", - "@vue/compiler-sfc": "3.4.27", - "@vue/runtime-dom": "3.4.27", - "@vue/server-renderer": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-dom": "3.4.29", + "@vue/compiler-sfc": "3.4.29", + "@vue/runtime-dom": "3.4.29", + "@vue/server-renderer": "3.4.29", + "@vue/shared": "3.4.29" }, "peerDependencies": { "typescript": "*" @@ -6777,27 +6634,10 @@ } } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" - } - }, - "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/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" }, "node_modules/which": { "version": "2.0.2", @@ -6995,9 +6835,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", - "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index 79992c6..df5b363 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,6 @@ "lint": "next lint" }, "dependencies": { - "@ai-sdk/openai": "^0.0.17", - "@huggingface/inference": "^2.7.0", "@prisma/client": "^5.14.0", "@radix-ui/react-slot": "^1.0.2", "ai": "^3.1.17", @@ -18,7 +16,7 @@ "clsx": "^2.1.1", "lucide-react": "^0.379.0", "next": "14.2.3", - "openai": "^4.47.2", + "ollama": "^0.5.2", "prisma": "^5.14.0", "react": "^18", "react-dom": "^18", diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/actions.ts b/src/app/actions.ts index 350ac0d..1fcc902 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -1,16 +1,12 @@ "use server" -import prisma from '@/lib/prisma'; -import { extract, toMarkdown } from '@/lib/format'; -import { HfInference } from '@huggingface/inference'; -import { createStreamableValue } from 'ai/rsc'; +import prisma from '@/lib/prisma' +import { extract, toMarkdown } from '@/lib/format' +import { Ollama } from 'ollama' +import { createStreamableValue } from 'ai/rsc' export async function recommend(messages: Message[]) { - - const inference = new HfInference(process.env.HUGGINGFACE_TOKEN); - const embedding = await inference.featureExtraction({ - model: "sentence-transformers/all-MiniLM-L6-v2", - inputs: messages[messages.length - 1].content, - }); + const ollama = new Ollama({ host: (process.env.OLLAMA_SCHEME || 'http')+'://'+(process.env.OLLAMA_HOST || 'localhost')+':'+(process.env.OLLAMA_PORT || 11434) }) + const embedding = await ollama.embeddings({ model: process.env.EMBEDDING_MODEL || 'not-defined', prompt: messages[messages.length - 1].content }) // Query the database for similar watches const watches: Watch[] = await prisma.$queryRaw` @@ -29,34 +25,42 @@ export async function recommend(messages: Message[]) { complications, power_reserve, price_usd, - 1 - (embedding <=> ${embedding}::vector) as similarity + 1 - (embedding <=> ${embedding['embedding']}::vector) as similarity FROM watches ORDER BY similarity DESC LIMIT 5; ` - - const stream = createStreamableValue(''); - (async () => { + const stream = createStreamableValue('') + const message = { + 'role': 'user', + 'content': ` +You are an helpful AI that will recommend watches to the user. + +The watch selected is below with its attributes as a list. +Your response is a markdown document. +Write a paragraph of why this watch matches their request using the watch attributes. + +The recommended watch is: + +${toMarkdown(watches[0])}. + +Create a table of the following data titled as alternatives: + +${watches.map((watch: Watch) => extract(watch)).join('\n')} +`, + }; + (async () => { // Update the stream with all the watches[0] properties in a markdown table stream.append(toMarkdown(watches[0])) stream.append(`\n\n\n\n`) - for await (const chunk of inference.chatCompletionStream({ - model: "mistralai/Mistral-7B-Instruct-v0.2", - messages: [ - { - 'role': 'user', - 'content': `You are an helpful AI that will recommend watches to the user. The watch selected is below with its attributes as a list. Your response is a markdown document. Write a paragrah of why this watch matches their request using the watch attributes. The recommended watch is: ${toMarkdown(watches[0])}. Create a table of the following data titled as alternatives: ${watches.map((watch: Watch) => extract(watch)).join('\n')}` - } - ], - max_tokens: 500, - temperature: 0, - })) { - stream.update(chunk.choices[0].delta.content!); + const response = await ollama.chat({ model: process.env.CHAT_MODEL || 'not-defined', messages: [message], stream: true }) + for await (const part of response) { + stream.update(part.message.content) } - stream.done(); - })(); + stream.done() + })() - return { output: stream.value }; -} \ No newline at end of file + return { output: stream.value } +} diff --git a/vectorize/requirements-mac.txt b/vectorize/requirements-mac.txt deleted file mode 100644 index 34df3d1..0000000 --- a/vectorize/requirements-mac.txt +++ /dev/null @@ -1,35 +0,0 @@ -certifi==2024.2.2 -charset-normalizer==3.3.2 -filelock==3.14.0 -fsspec==2024.5.0 -huggingface-hub==0.23.2 -idna==3.7 -Jinja2==3.1.4 -joblib==1.4.2 -MarkupSafe==2.1.5 -mpmath==1.3.0 -networkx==3.3 -numpy==1.26.4 -packaging==24.0 -pandas==2.2.2 -pillow==10.3.0 -psycopg2-binary==2.9.9 -python-dateutil==2.9.0.post0 -pytz==2024.1 -PyYAML==6.0.1 -regex==2024.5.15 -requests==2.32.3 -safetensors==0.4.3 -scikit-learn==1.5.0 -scipy==1.13.1 -sentence-transformers==3.0.0 -six==1.16.0 -sympy==1.12.1 -threadpoolctl==3.5.0 -tokenizers==0.19.1 -torch==2.3.0 -tqdm==4.66.4 -transformers==4.41.2 -typing_extensions==4.12.0 -tzdata==2024.1 -urllib3==2.2.1 diff --git a/vectorize/requirements.txt b/vectorize/requirements.txt index dc866c0..bd9fc45 100644 --- a/vectorize/requirements.txt +++ b/vectorize/requirements.txt @@ -1,36 +1,2 @@ --f https://download.pytorch.org/whl/torch_stable.html -torch==2.3.0+cpu -certifi==2024.2.2 -charset-normalizer==3.3.2 -filelock==3.14.0 -fsspec==2024.5.0 -huggingface-hub==0.23.2 -idna==3.7 -Jinja2==3.1.4 -joblib==1.4.2 -MarkupSafe==2.1.5 -mpmath==1.3.0 -networkx==3.3 -numpy==1.26.4 -packaging==24.0 -pandas==2.2.2 -pillow==10.3.0 -psycopg2-binary==2.9.9 -python-dateutil==2.9.0.post0 -pytz==2024.1 -PyYAML==6.0.1 -regex==2024.5.15 -requests==2.32.3 -safetensors==0.4.3 -scikit-learn==1.5.0 -scipy==1.13.1 -sentence-transformers==3.0.0 -six==1.16.0 -sympy==1.12.1 -threadpoolctl==3.5.0 -tokenizers==0.19.1 -tqdm==4.66.4 -transformers==4.41.2 -typing_extensions==4.12.0 -tzdata==2024.1 -urllib3==2.2.1 +ollama==0.2.1 +psycopg2_binary==2.9.9 diff --git a/vectorize/vectorize.py b/vectorize/vectorize.py index 20abb17..444a5a6 100644 --- a/vectorize/vectorize.py +++ b/vectorize/vectorize.py @@ -1,17 +1,9 @@ -import pandas as pd -from sentence_transformers import SentenceTransformer +import ollama import psycopg2 import os from decimal import Decimal import re -from pprint import pprint - -def generate_embeddings(data): - # Generate embeddings for the extracted data - model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') - embeddings = model.encode(data) - # Return the embeddings - return embeddings +import csv def prepare_database(conn, cur): # cur.execute("CREATE EXTENSION IF NOT EXISTS vector") @@ -41,59 +33,44 @@ def prepare_database(conn, cur): def main(): conn = psycopg2.connect( - dbname=os.getenv('DB_PATH'), - user=os.getenv('DB_USERNAME'), - password=os.getenv('DB_PASSWORD'), - host=os.getenv('DB_HOST'), - port=os.getenv('DB_PORT') - ) - + dbname=os.getenv('DB_PATH'), + user=os.getenv('DB_USERNAME'), + password=os.getenv('DB_PASSWORD'), + host=os.getenv('DB_HOST'), + port=os.getenv('DB_PORT') + ) cur = conn.cursor() + prepare_database(conn, cur) + model = os.getenv('EMBEDDING_MODEL') - prepare_database(conn, cur); - - # Create an empty array to store the extracted data - extracted_data = [] + with open('data/watches-full.csv', 'r', encoding='utf-8-sig') as file: + reader = csv.DictReader(file) + for row in reader: + extract = [f"{column}: {value}" for column, value in row.items()] + cur.execute( + 'INSERT INTO watches ("brand", "model", "case_material", "strap_material", "movement_type", "water_resistance", "case_diameter_mm", "case_thickness_mm", "band_width_mm", "dial_color", "crystal_material", "complications", "power_reserve", "price_usd", "embedding") VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', + ( + row['Brand'], + row['Model'], + row['Case Material'], + row['Strap Material'], + row['Movement Type'], + row['Water Resistance'], + Decimal(row['Case Diameter (mm)']), + Decimal(row['Case Thickness (mm)']), + Decimal(row['Band Width (mm)']), + row['Dial Color'], + row['Crystal Material'], + row['Complications'], + row['Power Reserve'], + int(re.sub("[^0-9.]", "", row['Price (USD)'])), + ollama.embeddings(model=model, prompt="\n".join(extract))['embedding'], + ) + ) - df = pd.read_csv('data/watches-full.csv') - # Loop over df and print each row with a : separator between columns - for index, row in df.iterrows(): - # Add a : separator between the column name and value - extract = [f"{column}: {value}" for column, value in row.items()] - # Join the columns into a single string - extract = "\r\n".join(extract) - # Append the extract to the extracted_data array - extracted_data.append(extract) - - # Generate embeddings for the extracted data - embeddings = generate_embeddings(extracted_data) - - # Store the watch and the embedding in pgsql - for index, row in df.iterrows(): - cur.execute( - 'INSERT INTO watches ("brand", "model", "case_material", "strap_material", "movement_type", "water_resistance", "case_diameter_mm", "case_thickness_mm", "band_width_mm", "dial_color", "crystal_material", "complications", "power_reserve", "price_usd", "embedding") VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', - ( - row.loc['Brand'], - row.loc['Model'], - row.loc['Case Material'], - row.loc['Strap Material'], - row.loc['Movement Type'], - row.loc['Water Resistance'], - Decimal(row.loc['Case Diameter (mm)']), - Decimal(row.loc['Case Thickness (mm)']), - Decimal(row.loc['Band Width (mm)']), - row.loc['Dial Color'], - row.loc['Crystal Material'], - row.loc['Complications'], - row.loc['Power Reserve'], - int(re.sub("[^0-9.]", "", row.loc['Price (USD)'])), - embeddings[index].tolist()) - ) - conn.commit() - - # Close the cursor and connection + conn.commit() cur.close() conn.close() if __name__ == "__main__": - main() \ No newline at end of file + main()