Upload folder using huggingface_hub
Browse files- .env.example +13 -0
- .gitattributes +4 -0
- .gitignore +15 -0
- README.md +212 -12
- application/deployment.xml +5 -0
- application/schemas/pdf_page.sd +410 -0
- application/search/query-profiles/default.xml +2 -0
- application/search/query-profiles/types/root.xml +2 -0
- application/services.xml +54 -0
- prepare_feed_deploy.py +995 -0
- pyproject.toml +114 -0
- src/README.md +19 -0
- src/backend/__init__.py +0 -0
- src/backend/cache.py +26 -0
- src/backend/colpali.py +281 -0
- src/backend/stopwords.py +18 -0
- src/backend/testquery.py +3013 -0
- src/backend/vespa_app.py +458 -0
- src/frontend/__init__.py +0 -0
- src/frontend/app.py +768 -0
- src/frontend/layout.py +171 -0
- src/globals.css +293 -0
- src/icons.py +1 -0
- src/main.py +420 -0
- src/output.css +2973 -0
- src/requirements.txt +540 -0
- src/static/img/colpali_child.png +3 -0
- src/static/img/linkedin.svg +3 -0
- src/static/img/vespa-colpali.png +3 -0
- src/static/img/visual-retrieval-demoapp-arch.png +3 -0
- src/static/img/x.svg +3 -0
- src/static/js/highlightjs-theme.js +23 -0
- src/tailwind.config.js +243 -0
- src/tailwindcss +3 -0
- uv.lock +0 -0
- vespa_feed_to_hf_dataset.py +42 -0
.env.example
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
VESPA_APP_TOKEN_URL=https://abcde.z.vespa-app.cloud
|
| 2 |
+
VESPA_APP_MTLS_URL=https://fghjkl.z.vespa-app.cloud
|
| 3 |
+
HF_TOKEN=hf_xxxxxxxxxx
|
| 4 |
+
VESPA_CLOUD_SECRET_TOKEN=vespa_cloud_xxxxxxxx
|
| 5 |
+
GEMINI_API_KEY=
|
| 6 |
+
USE_MTLS=false
|
| 7 |
+
VESPA_CLOUD_MTLS_KEY="-----BEGIN PRIVATE KEY-----
|
| 8 |
+
...
|
| 9 |
+
-----END PRIVATE KEY-----"
|
| 10 |
+
VESPA_CLOUD_MTLS_CERT="-----BEGIN CERTIFICATE-----
|
| 11 |
+
...
|
| 12 |
+
-----END CERTIFICATE-----"
|
| 13 |
+
HOT_RELOAD=true
|
.gitattributes
CHANGED
|
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
src/static/img/colpali_child.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
src/static/img/vespa-colpali.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
src/static/img/visual-retrieval-demoapp-arch.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
src/tailwindcss filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.sesskey
|
| 2 |
+
.venv/
|
| 3 |
+
__pycache__/
|
| 4 |
+
ipynb_checkpoints/
|
| 5 |
+
.python-version
|
| 6 |
+
.env
|
| 7 |
+
template/
|
| 8 |
+
*.json
|
| 9 |
+
output/
|
| 10 |
+
pdfs/
|
| 11 |
+
colpalidemo/
|
| 12 |
+
src/static/full_images/
|
| 13 |
+
src/static/sim_maps/
|
| 14 |
+
embeddings/
|
| 15 |
+
hf_dataset/
|
README.md
CHANGED
|
@@ -1,12 +1,212 @@
|
|
| 1 |
-
---
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
|
| 2 |
+
|
| 3 |
+
<picture>
|
| 4 |
+
<source media="(prefers-color-scheme: dark)" srcset="https://assets.vespa.ai/logos/Vespa-logo-green-RGB.svg">
|
| 5 |
+
<source media="(prefers-color-scheme: light)" srcset="https://assets.vespa.ai/logos/Vespa-logo-dark-RGB.svg">
|
| 6 |
+
<img alt="#Vespa" width="200" src="https://assets.vespa.ai/logos/Vespa-logo-dark-RGB.svg" style="margin-bottom: 25px;">
|
| 7 |
+
</picture>
|
| 8 |
+
|
| 9 |
+
# 🔍 Visual Retrieval ColPali 👀
|
| 10 |
+
|
| 11 |
+
This readme contains the code for a web app including a frontend that can be set up as a user facing interface.
|
| 12 |
+
|
| 13 |
+
## Why?
|
| 14 |
+
|
| 15 |
+
To enable _you_ to showcase the power of ColPali and Vespa to your users, and to provide a starting point for your own projects.
|
| 16 |
+
|
| 17 |
+
> "But I only know Python, how can I create a web app that's not Gradio or Streamlit?" 🤔
|
| 18 |
+
|
| 19 |
+
No worries! This project uses [FastHTML](https://fastht.ml/) to create a beautiful web app - and it's all Python! 🐍
|
| 20 |
+
|
| 21 |
+
Also, 👇
|
| 22 |
+
|
| 23 |
+
<a href="https://imgflip.com/i/98mhch"><img src="https://i.imgflip.com/98mhch.jpg" title="made at imgflip.com" alt="Funny meme about json output in demo"/></a>
|
| 24 |
+
|
| 25 |
+
As a prerequisite, you should run [this notebook](https://pyvespa.readthedocs.io/en/latest/examples/visual_pdf_rag_with_vespa_colpali_cloud.html)
|
| 26 |
+
to prepare the data and deploy the Vespa application.
|
| 27 |
+
|
| 28 |
+
## Setting up your .env variables
|
| 29 |
+
|
| 30 |
+
The following variables are required in your `.env` file for the application to be able to connect to the Vespa application and the Gemini API:
|
| 31 |
+
|
| 32 |
+
You can rename the `.env.example` file to `.env` and fill in the required values.
|
| 33 |
+
The other variables are optional, if you want to use mTLS authentication against the Vespa application.
|
| 34 |
+
|
| 35 |
+
```bash
|
| 36 |
+
VESPA_APP_TOKEN_URL=https://abcde.z.vespa-app.cloud
|
| 37 |
+
VESPA_CLOUD_SECRET_TOKEN=vespa_cloud_xxxxxxxx
|
| 38 |
+
GEMINI_API_KEY=asdf
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
If you want to deploy the application to Huggingface, you also need to set a `HF_TOKEN` variable, with write permissions.
|
| 42 |
+
This is personal, and must be created at [huggingface](https://huggingface.co/settings/tokens).
|
| 43 |
+
|
| 44 |
+
```bash
|
| 45 |
+
HF_TOKEN=hf_xxxxxxxxxx
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
## Setting up python environment
|
| 49 |
+
|
| 50 |
+
This application should work on Python 3.8 and above.
|
| 51 |
+
|
| 52 |
+
You can install the dependencies with `pip`, but we recommend using `uv`.
|
| 53 |
+
Skip to [Installing dependencies using `uv`](#installing-dependencies-using-uv) if you want to use `uv`.
|
| 54 |
+
|
| 55 |
+
### Installing dependencies using `pip`
|
| 56 |
+
|
| 57 |
+
You can install the dependencies with `pip`:
|
| 58 |
+
|
| 59 |
+
```bash
|
| 60 |
+
pip install -r src/requirements.txt
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### Installing dependencies using `uv`
|
| 64 |
+
|
| 65 |
+
We recommend installing the amazing `uv` to manage your python environment:
|
| 66 |
+
See also [installation - uv docs](https://docs.astral.sh/uv/getting-started/installation/) for other installation options.
|
| 67 |
+
|
| 68 |
+
```bash
|
| 69 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
Then, create a virtual environment:
|
| 73 |
+
|
| 74 |
+
```bash
|
| 75 |
+
uv venv
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
Activate the virtual environment:
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
source .venv/bin/activate
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
Sync your virtual environment with the dependencies:
|
| 85 |
+
|
| 86 |
+
```bash
|
| 87 |
+
uv sync --extra dev
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
## Running the application locally
|
| 91 |
+
|
| 92 |
+
To run the application locally, you can change into the `src` directory and run:
|
| 93 |
+
|
| 94 |
+
```bash
|
| 95 |
+
python main.py
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
This will start a local server, and you can access the application at `http://localhost:7860`.
|
| 99 |
+
|
| 100 |
+
## Deploy to huggingface 🤗 spaces
|
| 101 |
+
|
| 102 |
+
### Compiling dependencies
|
| 103 |
+
|
| 104 |
+
Before a deploy, make sure to run this to compile the `uv` lock file to `requirements.txt` if you have made changes to the dependencies:
|
| 105 |
+
|
| 106 |
+
```bash
|
| 107 |
+
uv pip compile pyproject.toml -o src/requirements.txt
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
This will make sure that the dependencies in your `pyproject.toml` are compiled to the `requirements.txt` file, which is used by the huggingface space.
|
| 111 |
+
|
| 112 |
+
### Deploying to huggingface
|
| 113 |
+
|
| 114 |
+
Note that you need to set `HF_TOKEN` environment variable first.
|
| 115 |
+
This is personal, and must be created at [huggingface](https://huggingface.co/settings/tokens).
|
| 116 |
+
Make sure the token has `write` access.
|
| 117 |
+
Be aware that this will not delete existing files, only modify or add,
|
| 118 |
+
see [huggingface-cli](https://huggingface.co/docs/huggingface_hub/en/guides/upload#upload-from-the-cli) for more
|
| 119 |
+
information.
|
| 120 |
+
|
| 121 |
+
#### Update your space configuration
|
| 122 |
+
|
| 123 |
+
The `src/README.md` file contains the configuration for the space.
|
| 124 |
+
Feel free to update this file to match your own configuration - name, description, etc.
|
| 125 |
+
|
| 126 |
+
Note that we can actually use the `gradio` SDK of spaces, to serve FastHTML apps as well, as long as we serve the app on port `7860`.
|
| 127 |
+
See [Custom python spaces](https://huggingface.co/docs/hub/en/spaces-sdks-python) for more information.
|
| 128 |
+
|
| 129 |
+
#### Upload the files
|
| 130 |
+
|
| 131 |
+
To deploy, run
|
| 132 |
+
|
| 133 |
+
(Replace `vespa-engine/colpali-vespa-visual-retrieval` with your own huggingface user/repo name, does not need to exist beforehand)
|
| 134 |
+
|
| 135 |
+
```bash
|
| 136 |
+
huggingface-cli upload vespa-engine/colpali-vespa-visual-retrieval src . --repo-type=space
|
| 137 |
+
```
|
| 138 |
+
|
| 139 |
+
Note that we upload only the `src` directory.
|
| 140 |
+
|
| 141 |
+
## Development
|
| 142 |
+
|
| 143 |
+
This section applies if you want to make changes to the web app.
|
| 144 |
+
|
| 145 |
+
### Adding dependencies
|
| 146 |
+
|
| 147 |
+
To add dependencies, you can add them to the `pyproject.toml` file and run:
|
| 148 |
+
|
| 149 |
+
```bash
|
| 150 |
+
uv compile
|
| 151 |
+
```
|
| 152 |
+
|
| 153 |
+
and then sync the dependencies:
|
| 154 |
+
|
| 155 |
+
```bash
|
| 156 |
+
uv sync --extra dev
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
### Making changes to CSS
|
| 160 |
+
|
| 161 |
+
To make changes to output.css apply, run
|
| 162 |
+
|
| 163 |
+
```bash
|
| 164 |
+
shad4fast watch # watches all files passed through the tailwind.config.js content section
|
| 165 |
+
|
| 166 |
+
shad4fast build # minifies the current output.css file to reduce bundle size in production.
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
### Instructions on creating and feeding the full dataset
|
| 170 |
+
|
| 171 |
+
This section is only relevant if you want to create and feed the full dataset to Vespa.
|
| 172 |
+
The notebook referenced in the beginning of this readme should be sufficient if you just want to spin up a scaled down version of the demo.
|
| 173 |
+
|
| 174 |
+
#### Prepare data and Vespa application
|
| 175 |
+
|
| 176 |
+
First, install `uv`:
|
| 177 |
+
|
| 178 |
+
```bash
|
| 179 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
Then, run:
|
| 183 |
+
|
| 184 |
+
```bash
|
| 185 |
+
uv sync --extra dev --extra feed
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
#### Converting to notebook
|
| 189 |
+
|
| 190 |
+
If you want to run the `prepare_feed_deploy.py` as a notebook, you can convert it using `jupytext`:
|
| 191 |
+
|
| 192 |
+
Convert the `prepare_feed_deploy.py` to notebook to:
|
| 193 |
+
|
| 194 |
+
```bash
|
| 195 |
+
jupytext --to notebook prepare_feed_deploy.py
|
| 196 |
+
```
|
| 197 |
+
|
| 198 |
+
And launch a Jupyter instance with:
|
| 199 |
+
|
| 200 |
+
```bash
|
| 201 |
+
uv run --with jupyter jupyter lab
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
## Credits
|
| 205 |
+
|
| 206 |
+
Huge thanks to the amazing projects that made it a joy to create this demo 🙏🙌
|
| 207 |
+
|
| 208 |
+
- Freeing us from python dependency hell - [uv](https://astral.sh/uv/)
|
| 209 |
+
- Allowing us to build **beautiful** full stack web apps in Python [FastHTML](https://fastht.ml/)
|
| 210 |
+
- Introducing the ColPali architecture - [ColPali](https://huggingface.co/vidore/colpali-v1.2)
|
| 211 |
+
- Adding `shadcn` components to FastHTML - [Shad4Fast](https://www.shad4fasthtml.com/)
|
| 212 |
+
|
application/deployment.xml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<deployment version="1.0">
|
| 2 |
+
<prod>
|
| 3 |
+
<region>aws-us-east-1c</region>
|
| 4 |
+
</prod>
|
| 5 |
+
</deployment>
|
application/schemas/pdf_page.sd
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
schema pdf_page {
|
| 2 |
+
document pdf_page {
|
| 3 |
+
field id type string {
|
| 4 |
+
indexing: summary | index
|
| 5 |
+
match {
|
| 6 |
+
word
|
| 7 |
+
}
|
| 8 |
+
}
|
| 9 |
+
field url type string {
|
| 10 |
+
indexing: summary | index
|
| 11 |
+
}
|
| 12 |
+
field year type int {
|
| 13 |
+
indexing: summary | attribute
|
| 14 |
+
}
|
| 15 |
+
field title type string {
|
| 16 |
+
indexing: summary | index
|
| 17 |
+
index: enable-bm25
|
| 18 |
+
match {
|
| 19 |
+
text
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
field page_number type int {
|
| 23 |
+
indexing: summary | attribute
|
| 24 |
+
}
|
| 25 |
+
field blur_image type raw {
|
| 26 |
+
indexing: summary
|
| 27 |
+
}
|
| 28 |
+
field full_image type raw {
|
| 29 |
+
indexing: summary
|
| 30 |
+
}
|
| 31 |
+
field text type string {
|
| 32 |
+
indexing: summary | index
|
| 33 |
+
index: enable-bm25
|
| 34 |
+
match {
|
| 35 |
+
text
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
field embedding type tensor<int8>(patch{}, v[16]) {
|
| 39 |
+
indexing: attribute | index
|
| 40 |
+
attribute {
|
| 41 |
+
distance-metric: hamming
|
| 42 |
+
}
|
| 43 |
+
index {
|
| 44 |
+
hnsw {
|
| 45 |
+
max-links-per-node: 32
|
| 46 |
+
neighbors-to-explore-at-insert: 400
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
field questions type array<string> {
|
| 51 |
+
indexing: summary | attribute
|
| 52 |
+
summary: matched-elements-only
|
| 53 |
+
}
|
| 54 |
+
field queries type array<string> {
|
| 55 |
+
indexing: summary | attribute
|
| 56 |
+
summary: matched-elements-only
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
fieldset default {
|
| 60 |
+
fields: title, text
|
| 61 |
+
}
|
| 62 |
+
rank-profile bm25 {
|
| 63 |
+
inputs {
|
| 64 |
+
query(qt) tensor<float>(querytoken{}, v[128])
|
| 65 |
+
|
| 66 |
+
}
|
| 67 |
+
function similarities() {
|
| 68 |
+
expression {
|
| 69 |
+
|
| 70 |
+
sum(
|
| 71 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
function normalized() {
|
| 77 |
+
expression {
|
| 78 |
+
|
| 79 |
+
(similarities - reduce(similarities, min)) / (reduce((similarities - reduce(similarities, min)), max)) * 2 - 1
|
| 80 |
+
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
function quantized() {
|
| 84 |
+
expression {
|
| 85 |
+
|
| 86 |
+
cell_cast(normalized * 127.999, int8)
|
| 87 |
+
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
first-phase {
|
| 91 |
+
expression {
|
| 92 |
+
bm25(title) + bm25(text)
|
| 93 |
+
}
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
rank-profile bm25_sim inherits bm25 {
|
| 97 |
+
first-phase {
|
| 98 |
+
expression {
|
| 99 |
+
bm25(title) + bm25(text)
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
summary-features {
|
| 103 |
+
quantized
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
rank-profile colpali {
|
| 107 |
+
inputs {
|
| 108 |
+
query(rq0) tensor<int8>(v[16])
|
| 109 |
+
query(rq1) tensor<int8>(v[16])
|
| 110 |
+
query(rq2) tensor<int8>(v[16])
|
| 111 |
+
query(rq3) tensor<int8>(v[16])
|
| 112 |
+
query(rq4) tensor<int8>(v[16])
|
| 113 |
+
query(rq5) tensor<int8>(v[16])
|
| 114 |
+
query(rq6) tensor<int8>(v[16])
|
| 115 |
+
query(rq7) tensor<int8>(v[16])
|
| 116 |
+
query(rq8) tensor<int8>(v[16])
|
| 117 |
+
query(rq9) tensor<int8>(v[16])
|
| 118 |
+
query(rq10) tensor<int8>(v[16])
|
| 119 |
+
query(rq11) tensor<int8>(v[16])
|
| 120 |
+
query(rq12) tensor<int8>(v[16])
|
| 121 |
+
query(rq13) tensor<int8>(v[16])
|
| 122 |
+
query(rq14) tensor<int8>(v[16])
|
| 123 |
+
query(rq15) tensor<int8>(v[16])
|
| 124 |
+
query(rq16) tensor<int8>(v[16])
|
| 125 |
+
query(rq17) tensor<int8>(v[16])
|
| 126 |
+
query(rq18) tensor<int8>(v[16])
|
| 127 |
+
query(rq19) tensor<int8>(v[16])
|
| 128 |
+
query(rq20) tensor<int8>(v[16])
|
| 129 |
+
query(rq21) tensor<int8>(v[16])
|
| 130 |
+
query(rq22) tensor<int8>(v[16])
|
| 131 |
+
query(rq23) tensor<int8>(v[16])
|
| 132 |
+
query(rq24) tensor<int8>(v[16])
|
| 133 |
+
query(rq25) tensor<int8>(v[16])
|
| 134 |
+
query(rq26) tensor<int8>(v[16])
|
| 135 |
+
query(rq27) tensor<int8>(v[16])
|
| 136 |
+
query(rq28) tensor<int8>(v[16])
|
| 137 |
+
query(rq29) tensor<int8>(v[16])
|
| 138 |
+
query(rq30) tensor<int8>(v[16])
|
| 139 |
+
query(rq31) tensor<int8>(v[16])
|
| 140 |
+
query(rq32) tensor<int8>(v[16])
|
| 141 |
+
query(rq33) tensor<int8>(v[16])
|
| 142 |
+
query(rq34) tensor<int8>(v[16])
|
| 143 |
+
query(rq35) tensor<int8>(v[16])
|
| 144 |
+
query(rq36) tensor<int8>(v[16])
|
| 145 |
+
query(rq37) tensor<int8>(v[16])
|
| 146 |
+
query(rq38) tensor<int8>(v[16])
|
| 147 |
+
query(rq39) tensor<int8>(v[16])
|
| 148 |
+
query(rq40) tensor<int8>(v[16])
|
| 149 |
+
query(rq41) tensor<int8>(v[16])
|
| 150 |
+
query(rq42) tensor<int8>(v[16])
|
| 151 |
+
query(rq43) tensor<int8>(v[16])
|
| 152 |
+
query(rq44) tensor<int8>(v[16])
|
| 153 |
+
query(rq45) tensor<int8>(v[16])
|
| 154 |
+
query(rq46) tensor<int8>(v[16])
|
| 155 |
+
query(rq47) tensor<int8>(v[16])
|
| 156 |
+
query(rq48) tensor<int8>(v[16])
|
| 157 |
+
query(rq49) tensor<int8>(v[16])
|
| 158 |
+
query(rq50) tensor<int8>(v[16])
|
| 159 |
+
query(rq51) tensor<int8>(v[16])
|
| 160 |
+
query(rq52) tensor<int8>(v[16])
|
| 161 |
+
query(rq53) tensor<int8>(v[16])
|
| 162 |
+
query(rq54) tensor<int8>(v[16])
|
| 163 |
+
query(rq55) tensor<int8>(v[16])
|
| 164 |
+
query(rq56) tensor<int8>(v[16])
|
| 165 |
+
query(rq57) tensor<int8>(v[16])
|
| 166 |
+
query(rq58) tensor<int8>(v[16])
|
| 167 |
+
query(rq59) tensor<int8>(v[16])
|
| 168 |
+
query(rq60) tensor<int8>(v[16])
|
| 169 |
+
query(rq61) tensor<int8>(v[16])
|
| 170 |
+
query(rq62) tensor<int8>(v[16])
|
| 171 |
+
query(rq63) tensor<int8>(v[16])
|
| 172 |
+
query(qt) tensor<float>(querytoken{}, v[128])
|
| 173 |
+
query(qtb) tensor<int8>(querytoken{}, v[16])
|
| 174 |
+
|
| 175 |
+
}
|
| 176 |
+
function similarities() {
|
| 177 |
+
expression {
|
| 178 |
+
|
| 179 |
+
sum(
|
| 180 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
function normalized() {
|
| 186 |
+
expression {
|
| 187 |
+
|
| 188 |
+
(similarities - reduce(similarities, min)) / (reduce((similarities - reduce(similarities, min)), max)) * 2 - 1
|
| 189 |
+
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
function quantized() {
|
| 193 |
+
expression {
|
| 194 |
+
|
| 195 |
+
cell_cast(normalized * 127.999, int8)
|
| 196 |
+
|
| 197 |
+
}
|
| 198 |
+
}
|
| 199 |
+
function max_sim() {
|
| 200 |
+
expression {
|
| 201 |
+
|
| 202 |
+
sum(
|
| 203 |
+
reduce(
|
| 204 |
+
sum(
|
| 205 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 206 |
+
),
|
| 207 |
+
max, patch
|
| 208 |
+
),
|
| 209 |
+
querytoken
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
function max_sim_binary() {
|
| 215 |
+
expression {
|
| 216 |
+
|
| 217 |
+
sum(
|
| 218 |
+
reduce(
|
| 219 |
+
1 / (1 + sum(
|
| 220 |
+
hamming(query(qtb), attribute(embedding)), v)
|
| 221 |
+
),
|
| 222 |
+
max, patch
|
| 223 |
+
),
|
| 224 |
+
querytoken
|
| 225 |
+
)
|
| 226 |
+
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
first-phase {
|
| 230 |
+
expression {
|
| 231 |
+
max_sim_binary
|
| 232 |
+
}
|
| 233 |
+
}
|
| 234 |
+
second-phase {
|
| 235 |
+
rerank-count: 10
|
| 236 |
+
expression {
|
| 237 |
+
max_sim
|
| 238 |
+
}
|
| 239 |
+
}
|
| 240 |
+
}
|
| 241 |
+
rank-profile colpali_sim inherits colpali {
|
| 242 |
+
first-phase {
|
| 243 |
+
expression {
|
| 244 |
+
max_sim_binary
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
summary-features {
|
| 248 |
+
quantized
|
| 249 |
+
}
|
| 250 |
+
}
|
| 251 |
+
rank-profile hybrid {
|
| 252 |
+
inputs {
|
| 253 |
+
query(rq0) tensor<int8>(v[16])
|
| 254 |
+
query(rq1) tensor<int8>(v[16])
|
| 255 |
+
query(rq2) tensor<int8>(v[16])
|
| 256 |
+
query(rq3) tensor<int8>(v[16])
|
| 257 |
+
query(rq4) tensor<int8>(v[16])
|
| 258 |
+
query(rq5) tensor<int8>(v[16])
|
| 259 |
+
query(rq6) tensor<int8>(v[16])
|
| 260 |
+
query(rq7) tensor<int8>(v[16])
|
| 261 |
+
query(rq8) tensor<int8>(v[16])
|
| 262 |
+
query(rq9) tensor<int8>(v[16])
|
| 263 |
+
query(rq10) tensor<int8>(v[16])
|
| 264 |
+
query(rq11) tensor<int8>(v[16])
|
| 265 |
+
query(rq12) tensor<int8>(v[16])
|
| 266 |
+
query(rq13) tensor<int8>(v[16])
|
| 267 |
+
query(rq14) tensor<int8>(v[16])
|
| 268 |
+
query(rq15) tensor<int8>(v[16])
|
| 269 |
+
query(rq16) tensor<int8>(v[16])
|
| 270 |
+
query(rq17) tensor<int8>(v[16])
|
| 271 |
+
query(rq18) tensor<int8>(v[16])
|
| 272 |
+
query(rq19) tensor<int8>(v[16])
|
| 273 |
+
query(rq20) tensor<int8>(v[16])
|
| 274 |
+
query(rq21) tensor<int8>(v[16])
|
| 275 |
+
query(rq22) tensor<int8>(v[16])
|
| 276 |
+
query(rq23) tensor<int8>(v[16])
|
| 277 |
+
query(rq24) tensor<int8>(v[16])
|
| 278 |
+
query(rq25) tensor<int8>(v[16])
|
| 279 |
+
query(rq26) tensor<int8>(v[16])
|
| 280 |
+
query(rq27) tensor<int8>(v[16])
|
| 281 |
+
query(rq28) tensor<int8>(v[16])
|
| 282 |
+
query(rq29) tensor<int8>(v[16])
|
| 283 |
+
query(rq30) tensor<int8>(v[16])
|
| 284 |
+
query(rq31) tensor<int8>(v[16])
|
| 285 |
+
query(rq32) tensor<int8>(v[16])
|
| 286 |
+
query(rq33) tensor<int8>(v[16])
|
| 287 |
+
query(rq34) tensor<int8>(v[16])
|
| 288 |
+
query(rq35) tensor<int8>(v[16])
|
| 289 |
+
query(rq36) tensor<int8>(v[16])
|
| 290 |
+
query(rq37) tensor<int8>(v[16])
|
| 291 |
+
query(rq38) tensor<int8>(v[16])
|
| 292 |
+
query(rq39) tensor<int8>(v[16])
|
| 293 |
+
query(rq40) tensor<int8>(v[16])
|
| 294 |
+
query(rq41) tensor<int8>(v[16])
|
| 295 |
+
query(rq42) tensor<int8>(v[16])
|
| 296 |
+
query(rq43) tensor<int8>(v[16])
|
| 297 |
+
query(rq44) tensor<int8>(v[16])
|
| 298 |
+
query(rq45) tensor<int8>(v[16])
|
| 299 |
+
query(rq46) tensor<int8>(v[16])
|
| 300 |
+
query(rq47) tensor<int8>(v[16])
|
| 301 |
+
query(rq48) tensor<int8>(v[16])
|
| 302 |
+
query(rq49) tensor<int8>(v[16])
|
| 303 |
+
query(rq50) tensor<int8>(v[16])
|
| 304 |
+
query(rq51) tensor<int8>(v[16])
|
| 305 |
+
query(rq52) tensor<int8>(v[16])
|
| 306 |
+
query(rq53) tensor<int8>(v[16])
|
| 307 |
+
query(rq54) tensor<int8>(v[16])
|
| 308 |
+
query(rq55) tensor<int8>(v[16])
|
| 309 |
+
query(rq56) tensor<int8>(v[16])
|
| 310 |
+
query(rq57) tensor<int8>(v[16])
|
| 311 |
+
query(rq58) tensor<int8>(v[16])
|
| 312 |
+
query(rq59) tensor<int8>(v[16])
|
| 313 |
+
query(rq60) tensor<int8>(v[16])
|
| 314 |
+
query(rq61) tensor<int8>(v[16])
|
| 315 |
+
query(rq62) tensor<int8>(v[16])
|
| 316 |
+
query(rq63) tensor<int8>(v[16])
|
| 317 |
+
query(qt) tensor<float>(querytoken{}, v[128])
|
| 318 |
+
query(qtb) tensor<int8>(querytoken{}, v[16])
|
| 319 |
+
|
| 320 |
+
}
|
| 321 |
+
function similarities() {
|
| 322 |
+
expression {
|
| 323 |
+
|
| 324 |
+
sum(
|
| 325 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 326 |
+
)
|
| 327 |
+
|
| 328 |
+
}
|
| 329 |
+
}
|
| 330 |
+
function normalized() {
|
| 331 |
+
expression {
|
| 332 |
+
|
| 333 |
+
(similarities - reduce(similarities, min)) / (reduce((similarities - reduce(similarities, min)), max)) * 2 - 1
|
| 334 |
+
|
| 335 |
+
}
|
| 336 |
+
}
|
| 337 |
+
function quantized() {
|
| 338 |
+
expression {
|
| 339 |
+
|
| 340 |
+
cell_cast(normalized * 127.999, int8)
|
| 341 |
+
|
| 342 |
+
}
|
| 343 |
+
}
|
| 344 |
+
function max_sim() {
|
| 345 |
+
expression {
|
| 346 |
+
|
| 347 |
+
sum(
|
| 348 |
+
reduce(
|
| 349 |
+
sum(
|
| 350 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 351 |
+
),
|
| 352 |
+
max, patch
|
| 353 |
+
),
|
| 354 |
+
querytoken
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
function max_sim_binary() {
|
| 360 |
+
expression {
|
| 361 |
+
|
| 362 |
+
sum(
|
| 363 |
+
reduce(
|
| 364 |
+
1 / (1 + sum(
|
| 365 |
+
hamming(query(qtb), attribute(embedding)), v)
|
| 366 |
+
),
|
| 367 |
+
max, patch
|
| 368 |
+
),
|
| 369 |
+
querytoken
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
first-phase {
|
| 375 |
+
expression {
|
| 376 |
+
max_sim_binary
|
| 377 |
+
}
|
| 378 |
+
}
|
| 379 |
+
second-phase {
|
| 380 |
+
rerank-count: 10
|
| 381 |
+
expression {
|
| 382 |
+
max_sim + 2 * (bm25(text) + bm25(title))
|
| 383 |
+
}
|
| 384 |
+
}
|
| 385 |
+
}
|
| 386 |
+
rank-profile hybrid_sim inherits hybrid {
|
| 387 |
+
first-phase {
|
| 388 |
+
expression {
|
| 389 |
+
max_sim_binary
|
| 390 |
+
}
|
| 391 |
+
}
|
| 392 |
+
summary-features {
|
| 393 |
+
quantized
|
| 394 |
+
}
|
| 395 |
+
}
|
| 396 |
+
document-summary default {
|
| 397 |
+
summary text {
|
| 398 |
+
bolding: on
|
| 399 |
+
}
|
| 400 |
+
summary snippet {
|
| 401 |
+
source: text
|
| 402 |
+
dynamic
|
| 403 |
+
}
|
| 404 |
+
from-disk
|
| 405 |
+
}
|
| 406 |
+
document-summary suggestions {
|
| 407 |
+
summary questions {}
|
| 408 |
+
from-disk
|
| 409 |
+
}
|
| 410 |
+
}
|
application/search/query-profiles/default.xml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<query-profile id="default" type="root">
|
| 2 |
+
</query-profile>
|
application/search/query-profiles/types/root.xml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<query-profile-type id="root">
|
| 2 |
+
</query-profile-type>
|
application/services.xml
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8" ?>
|
| 2 |
+
<services version="1.0">
|
| 3 |
+
<container id="colpalidemo_container" version="1.0">
|
| 4 |
+
<nodes count="2">
|
| 5 |
+
<resources vcpu="4.0" memory="16Gb" architecture="x86_64" storage-type="remote" disk="48Gb"/>
|
| 6 |
+
</nodes>
|
| 7 |
+
<search></search>
|
| 8 |
+
<document-api></document-api>
|
| 9 |
+
<document-processing></document-processing>
|
| 10 |
+
<clients>
|
| 11 |
+
<client id="mtls" permissions="read,write">
|
| 12 |
+
<certificate file="security/clients.pem"></certificate>
|
| 13 |
+
</client>
|
| 14 |
+
<client id="token_write" permissions="read,write">
|
| 15 |
+
<token id="colpalidemo_write"></token>
|
| 16 |
+
</client>
|
| 17 |
+
</clients>
|
| 18 |
+
<config name="container.qr-searchers">
|
| 19 |
+
<tag>
|
| 20 |
+
<bold>
|
| 21 |
+
<open><strong></open>
|
| 22 |
+
<close></strong></close>
|
| 23 |
+
</bold>
|
| 24 |
+
<separator>...</separator>
|
| 25 |
+
</tag>
|
| 26 |
+
</config>
|
| 27 |
+
</container>
|
| 28 |
+
<content id="colpalidemo_content" version="1.0">
|
| 29 |
+
<redundancy>2</redundancy>
|
| 30 |
+
<documents>
|
| 31 |
+
<document type="pdf_page" mode="index"></document>
|
| 32 |
+
</documents>
|
| 33 |
+
<nodes count="2">
|
| 34 |
+
<resources vcpu="8.0" memory="16Gb" architecture="arm64" storage-type="local" disk="474Gb"/>
|
| 35 |
+
</nodes>
|
| 36 |
+
<engine>
|
| 37 |
+
<proton>
|
| 38 |
+
<tuning>
|
| 39 |
+
<searchnode>
|
| 40 |
+
<requestthreads>
|
| 41 |
+
<persearch>4</persearch>
|
| 42 |
+
</requestthreads>
|
| 43 |
+
</searchnode>
|
| 44 |
+
</tuning>
|
| 45 |
+
</proton>
|
| 46 |
+
</engine>
|
| 47 |
+
<config name="vespa.config.search.summary.juniperrc">
|
| 48 |
+
<max_matches>2</max_matches>
|
| 49 |
+
<length>1000</length>
|
| 50 |
+
<surround_max>500</surround_max>
|
| 51 |
+
<min_length>300</min_length>
|
| 52 |
+
</config>
|
| 53 |
+
</content>
|
| 54 |
+
</services>
|
prepare_feed_deploy.py
ADDED
|
@@ -0,0 +1,995 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# # Visual PDF Retrieval - demo application
|
| 2 |
+
#
|
| 3 |
+
# In this notebook, we will prepare the Vespa backend application for our visual retrieval demo.
|
| 4 |
+
# We will use ColPali as the model to extract patch vectors from images of pdf pages.
|
| 5 |
+
# At query time, we use MaxSim to retrieve and/or (based on the configuration) rank the page results.
|
| 6 |
+
#
|
| 7 |
+
# To see the application in action, visit https://huggingface.co/spaces/vespa-engine/colpali-vespa-visual-retrieval
|
| 8 |
+
#
|
| 9 |
+
# The web application is written in FastHTML, meaning the complete application is written in python.
|
| 10 |
+
#
|
| 11 |
+
# The steps we will take in this notebook are:
|
| 12 |
+
#
|
| 13 |
+
# 0. Setup and configuration
|
| 14 |
+
# 1. Download the data
|
| 15 |
+
# 2. Prepare the data
|
| 16 |
+
# 3. Generate queries for evaluation and typeahead search suggestions
|
| 17 |
+
# 4. Deploy the Vespa application
|
| 18 |
+
# 5. Create the Vespa application
|
| 19 |
+
# 6. Feed the data to the Vespa application
|
| 20 |
+
#
|
| 21 |
+
# All the steps that are needed to provision the Vespa application, including feeding the data, can be done from this notebook.
|
| 22 |
+
# We have tried to make it easy for others to run this notebook, to create your own PDF Enterprise Search application using Vespa.
|
| 23 |
+
#
|
| 24 |
+
|
| 25 |
+
# ## 0. Setup and Configuration
|
| 26 |
+
#
|
| 27 |
+
|
| 28 |
+
# +
|
| 29 |
+
import os
|
| 30 |
+
import asyncio
|
| 31 |
+
import json
|
| 32 |
+
from typing import Tuple
|
| 33 |
+
import hashlib
|
| 34 |
+
import numpy as np
|
| 35 |
+
|
| 36 |
+
# Vespa
|
| 37 |
+
from vespa.package import (
|
| 38 |
+
ApplicationPackage,
|
| 39 |
+
Field,
|
| 40 |
+
Schema,
|
| 41 |
+
Document,
|
| 42 |
+
HNSW,
|
| 43 |
+
RankProfile,
|
| 44 |
+
Function,
|
| 45 |
+
FieldSet,
|
| 46 |
+
SecondPhaseRanking,
|
| 47 |
+
Summary,
|
| 48 |
+
DocumentSummary,
|
| 49 |
+
)
|
| 50 |
+
from vespa.deployment import VespaCloud
|
| 51 |
+
from vespa.application import Vespa
|
| 52 |
+
from vespa.io import VespaResponse
|
| 53 |
+
|
| 54 |
+
# Google Generative AI
|
| 55 |
+
import google.generativeai as genai
|
| 56 |
+
|
| 57 |
+
# Torch and other ML libraries
|
| 58 |
+
import torch
|
| 59 |
+
from torch.utils.data import DataLoader
|
| 60 |
+
from tqdm import tqdm
|
| 61 |
+
from pdf2image import convert_from_path
|
| 62 |
+
from pypdf import PdfReader
|
| 63 |
+
|
| 64 |
+
# ColPali model and processor
|
| 65 |
+
from colpali_engine.models import ColPali, ColPaliProcessor
|
| 66 |
+
from colpali_engine.utils.torch_utils import get_torch_device
|
| 67 |
+
from vidore_benchmark.utils.image_utils import scale_image, get_base64_image
|
| 68 |
+
|
| 69 |
+
# Other utilities
|
| 70 |
+
from bs4 import BeautifulSoup
|
| 71 |
+
import httpx
|
| 72 |
+
from urllib.parse import urljoin, urlparse
|
| 73 |
+
|
| 74 |
+
# Load environment variables
|
| 75 |
+
from dotenv import load_dotenv
|
| 76 |
+
|
| 77 |
+
load_dotenv()
|
| 78 |
+
|
| 79 |
+
# Avoid warning from huggingface tokenizers
|
| 80 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
| 81 |
+
# -
|
| 82 |
+
|
| 83 |
+
# ### Create a free trial in Vespa Cloud
|
| 84 |
+
#
|
| 85 |
+
# Create a tenant from [here](https://vespa.ai/free-trial/).
|
| 86 |
+
# The trial includes $300 credit.
|
| 87 |
+
# Take note of your tenant name.
|
| 88 |
+
#
|
| 89 |
+
|
| 90 |
+
VESPA_TENANT_NAME = "vespa-team"
|
| 91 |
+
|
| 92 |
+
# Here, set your desired application name. (Will be created in later steps)
|
| 93 |
+
# Note that you can not have hyphen `-` or underscore `_` in the application name.
|
| 94 |
+
#
|
| 95 |
+
|
| 96 |
+
VESPA_APPLICATION_NAME = "colpalidemo"
|
| 97 |
+
VESPA_SCHEMA_NAME = "pdf_page"
|
| 98 |
+
|
| 99 |
+
# Next, you need to create some tokens for feeding data, and querying the application.
|
| 100 |
+
# We recommend separate tokens for feeding and querying, (the former with write permission, and the latter with read permission).
|
| 101 |
+
# The tokens can be created from the [Vespa Cloud console](https://console.vespa-cloud.com/) in the 'Account' -> 'Tokens' section.
|
| 102 |
+
#
|
| 103 |
+
|
| 104 |
+
VESPA_TOKEN_ID_WRITE = "colpalidemo_write"
|
| 105 |
+
|
| 106 |
+
# We also need to set the value of the write token to be able to feed data to the Vespa application.
|
| 107 |
+
#
|
| 108 |
+
|
| 109 |
+
VESPA_CLOUD_SECRET_TOKEN = os.getenv("VESPA_CLOUD_SECRET_TOKEN") or input(
|
| 110 |
+
"Enter Vespa cloud secret token: "
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
# We will also use the Gemini API to create sample queries for our images.
|
| 114 |
+
# You can also use other VLM's to create these queries.
|
| 115 |
+
# Create a Gemini API key from [here](https://aistudio.google.com/app/apikey).
|
| 116 |
+
#
|
| 117 |
+
|
| 118 |
+
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") or input(
|
| 119 |
+
"Enter Google Generative AI API key: "
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
# +
|
| 123 |
+
MODEL_NAME = "vidore/colpali-v1.2"
|
| 124 |
+
|
| 125 |
+
# Configure Google Generative AI
|
| 126 |
+
genai.configure(api_key=GEMINI_API_KEY)
|
| 127 |
+
|
| 128 |
+
# Set device for Torch
|
| 129 |
+
device = get_torch_device("auto")
|
| 130 |
+
print(f"Using device: {device}")
|
| 131 |
+
|
| 132 |
+
# Load the ColPali model and processor
|
| 133 |
+
model = ColPali.from_pretrained(
|
| 134 |
+
MODEL_NAME,
|
| 135 |
+
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
|
| 136 |
+
device_map=device,
|
| 137 |
+
).eval()
|
| 138 |
+
|
| 139 |
+
processor = ColPaliProcessor.from_pretrained(MODEL_NAME)
|
| 140 |
+
# -
|
| 141 |
+
|
| 142 |
+
# ## 1. Download PDFs
|
| 143 |
+
#
|
| 144 |
+
# We are going to use public reports from the Norwegian Government Pension Fund Global (also known as the Oil Fund).
|
| 145 |
+
# The fund puts transparency at the forefront and publishes reports on its investments, holdings, and returns, as well as its strategy and governance.
|
| 146 |
+
#
|
| 147 |
+
# These reports are the ones we are going to use for this showcase.
|
| 148 |
+
# Here are some sample images:
|
| 149 |
+
#
|
| 150 |
+
# 
|
| 151 |
+
# 
|
| 152 |
+
#
|
| 153 |
+
|
| 154 |
+
# As we can see, a lot of the information is in the form of tables, charts and numbers.
|
| 155 |
+
# These are not easily extractable using pdf-readers or OCR tools.
|
| 156 |
+
#
|
| 157 |
+
|
| 158 |
+
# +
|
| 159 |
+
import requests
|
| 160 |
+
|
| 161 |
+
url = "https://www.nbim.no/en/publications/reports/"
|
| 162 |
+
response = requests.get(url)
|
| 163 |
+
response.raise_for_status()
|
| 164 |
+
html_content = response.text
|
| 165 |
+
|
| 166 |
+
# Parse with BeautifulSoup
|
| 167 |
+
soup = BeautifulSoup(html_content, "html.parser")
|
| 168 |
+
|
| 169 |
+
links = []
|
| 170 |
+
url_to_year = {}
|
| 171 |
+
|
| 172 |
+
# Find all the years
|
| 173 |
+
for year_section in soup.find_all("section", attrs={"data-name": "report-year"}):
|
| 174 |
+
year_id = year_section.get("data-filter-section", "")
|
| 175 |
+
year = year_id.replace("year-", "")
|
| 176 |
+
|
| 177 |
+
# Find the yearly report section
|
| 178 |
+
report_section = year_section.find("div", attrs={
|
| 179 |
+
"data-filter-section": "year",
|
| 180 |
+
"data-name": "report-type"
|
| 181 |
+
})
|
| 182 |
+
if not report_section:
|
| 183 |
+
continue
|
| 184 |
+
|
| 185 |
+
# Get the first link
|
| 186 |
+
report_link = report_section.select_one("ul.link-list a")
|
| 187 |
+
if not report_link:
|
| 188 |
+
continue
|
| 189 |
+
|
| 190 |
+
report_url = urljoin(url, report_link["href"])
|
| 191 |
+
|
| 192 |
+
# Visit the report page to find PDF download links
|
| 193 |
+
try:
|
| 194 |
+
report_response = requests.get(report_url)
|
| 195 |
+
report_response.raise_for_status()
|
| 196 |
+
report_soup = BeautifulSoup(report_response.text, "html.parser")
|
| 197 |
+
|
| 198 |
+
# Find only the first PDF download link with the specific class
|
| 199 |
+
pdf_link = report_soup.select_one("a.btn.btn-secondary[data-right-icon='download']")
|
| 200 |
+
if not pdf_link or not pdf_link["href"].endswith(".pdf"):
|
| 201 |
+
continue
|
| 202 |
+
|
| 203 |
+
pdf_url = urljoin(report_url, pdf_link["href"])
|
| 204 |
+
links.append(pdf_url)
|
| 205 |
+
url_to_year[pdf_url] = year
|
| 206 |
+
print(f"Found PDF: {pdf_url} (Year: {year})")
|
| 207 |
+
except Exception as e:
|
| 208 |
+
print(f"Error fetching report page {report_url}: {e}")
|
| 209 |
+
|
| 210 |
+
print(f"Found {len(links)} PDF links")
|
| 211 |
+
# -
|
| 212 |
+
|
| 213 |
+
# Limit the number of PDFs to download
|
| 214 |
+
NUM_PDFS = 2 # Set to None to download all PDFs
|
| 215 |
+
links = links[:NUM_PDFS] if NUM_PDFS else links
|
| 216 |
+
links
|
| 217 |
+
|
| 218 |
+
# +
|
| 219 |
+
from nest_asyncio import apply
|
| 220 |
+
from typing import List
|
| 221 |
+
|
| 222 |
+
apply()
|
| 223 |
+
|
| 224 |
+
max_attempts = 3
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
async def download_pdf(session, url, filename):
|
| 228 |
+
attempt = 0
|
| 229 |
+
while attempt < max_attempts:
|
| 230 |
+
try:
|
| 231 |
+
response = await session.get(url)
|
| 232 |
+
response.raise_for_status()
|
| 233 |
+
|
| 234 |
+
# Use Content-Disposition header to get the filename if available
|
| 235 |
+
content_disposition = response.headers.get("Content-Disposition")
|
| 236 |
+
if content_disposition:
|
| 237 |
+
import re
|
| 238 |
+
|
| 239 |
+
fname = re.findall('filename="(.+)"', content_disposition)
|
| 240 |
+
if fname:
|
| 241 |
+
filename = fname[0]
|
| 242 |
+
|
| 243 |
+
# Ensure the filename is safe to use on the filesystem
|
| 244 |
+
safe_filename = filename.replace("/", "_").replace("\\", "_")
|
| 245 |
+
if not safe_filename or safe_filename == "_":
|
| 246 |
+
print(f"Invalid filename: {filename}")
|
| 247 |
+
continue
|
| 248 |
+
|
| 249 |
+
filepath = os.path.join("pdfs", safe_filename)
|
| 250 |
+
with open(filepath, "wb") as f:
|
| 251 |
+
f.write(response.content)
|
| 252 |
+
print(f"Downloaded {safe_filename}")
|
| 253 |
+
return filepath
|
| 254 |
+
except Exception as e:
|
| 255 |
+
print(f"Error downloading {filename}: {e}")
|
| 256 |
+
print(f"Retrying ({attempt})...")
|
| 257 |
+
await asyncio.sleep(1) # Wait a bit before retrying
|
| 258 |
+
attempt += 1
|
| 259 |
+
return None
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
async def download_pdfs(links: List[str]) -> List[dict]:
|
| 263 |
+
"""Download PDFs from a list of URLs. Add the filename to the dictionary."""
|
| 264 |
+
async with httpx.AsyncClient() as client:
|
| 265 |
+
tasks = []
|
| 266 |
+
|
| 267 |
+
for idx, link in enumerate(links):
|
| 268 |
+
# Try to get the filename from the URL
|
| 269 |
+
path = urlparse(link).path
|
| 270 |
+
filename = os.path.basename(path)
|
| 271 |
+
|
| 272 |
+
# If filename is empty,skip
|
| 273 |
+
if not filename:
|
| 274 |
+
continue
|
| 275 |
+
tasks.append(download_pdf(client, link, filename))
|
| 276 |
+
|
| 277 |
+
# Run the tasks concurrently
|
| 278 |
+
paths = await asyncio.gather(*tasks)
|
| 279 |
+
pdf_files = [
|
| 280 |
+
{"url": link, "path": path} for link, path in zip(links, paths) if path
|
| 281 |
+
]
|
| 282 |
+
return pdf_files
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
# Create the pdfs directory if it doesn't exist
|
| 286 |
+
os.makedirs("pdfs", exist_ok=True)
|
| 287 |
+
# Now run the download_pdfs function with the URL
|
| 288 |
+
pdfs = asyncio.run(download_pdfs(links))
|
| 289 |
+
# -
|
| 290 |
+
|
| 291 |
+
pdfs
|
| 292 |
+
|
| 293 |
+
# ## 2. Convert PDFs to Images
|
| 294 |
+
#
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
# +
|
| 298 |
+
def get_pdf_images(pdf_path):
|
| 299 |
+
reader = PdfReader(pdf_path)
|
| 300 |
+
page_texts = []
|
| 301 |
+
for page_number in range(len(reader.pages)):
|
| 302 |
+
page = reader.pages[page_number]
|
| 303 |
+
text = page.extract_text()
|
| 304 |
+
page_texts.append(text)
|
| 305 |
+
images = convert_from_path(pdf_path)
|
| 306 |
+
# Convert to PIL images
|
| 307 |
+
assert len(images) == len(page_texts)
|
| 308 |
+
return images, page_texts
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
pdf_folder = "pdfs"
|
| 312 |
+
pdf_pages = []
|
| 313 |
+
for pdf in tqdm(pdfs):
|
| 314 |
+
pdf_file = pdf["path"]
|
| 315 |
+
title = os.path.splitext(os.path.basename(pdf_file))[0]
|
| 316 |
+
images, texts = get_pdf_images(pdf_file)
|
| 317 |
+
for page_no, (image, text) in enumerate(zip(images, texts)):
|
| 318 |
+
pdf_pages.append(
|
| 319 |
+
{
|
| 320 |
+
"title": title,
|
| 321 |
+
"year": int(url_to_year[pdf["url"]]),
|
| 322 |
+
"url": pdf["url"],
|
| 323 |
+
"path": pdf_file,
|
| 324 |
+
"image": image,
|
| 325 |
+
"text": text,
|
| 326 |
+
"page_no": page_no,
|
| 327 |
+
}
|
| 328 |
+
)
|
| 329 |
+
# -
|
| 330 |
+
|
| 331 |
+
len(pdf_pages)
|
| 332 |
+
|
| 333 |
+
# +
|
| 334 |
+
from collections import Counter
|
| 335 |
+
|
| 336 |
+
# Print the length of the text fields - mean, max and min
|
| 337 |
+
text_lengths = [len(page["text"]) for page in pdf_pages]
|
| 338 |
+
print(f"Mean text length: {np.mean(text_lengths)}")
|
| 339 |
+
print(f"Max text length: {np.max(text_lengths)}")
|
| 340 |
+
print(f"Min text length: {np.min(text_lengths)}")
|
| 341 |
+
print(f"Median text length: {np.median(text_lengths)}")
|
| 342 |
+
print(f"Number of text with length == 0: {Counter(text_lengths)[0]}")
|
| 343 |
+
# -
|
| 344 |
+
|
| 345 |
+
# ## 3. Generate Queries
|
| 346 |
+
#
|
| 347 |
+
# In this step, we want to generate queries for each page image.
|
| 348 |
+
# These will be useful for 2 reasons:
|
| 349 |
+
#
|
| 350 |
+
# 1. We can use these queries as typeahead suggestions in the search bar.
|
| 351 |
+
# 2. We can use the queries to generate an evaluation dataset. See [Improving Retrieval with LLM-as-a-judge](https://blog.vespa.ai/improving-retrieval-with-llm-as-a-judge/) for a deeper dive into this topic.
|
| 352 |
+
#
|
| 353 |
+
# The prompt for generating queries is taken from [this](https://danielvanstrien.xyz/posts/post-with-code/colpali/2024-09-23-generate_colpali_dataset.html#an-update-retrieval-focused-prompt) wonderful blog post by Daniel van Strien.
|
| 354 |
+
#
|
| 355 |
+
# We will use the Gemini API to generate these queries, with `gemini-1.5-flash-8b` as the model.
|
| 356 |
+
#
|
| 357 |
+
|
| 358 |
+
# +
|
| 359 |
+
from pydantic import BaseModel
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
class GeneratedQueries(BaseModel):
|
| 363 |
+
broad_topical_question: str
|
| 364 |
+
broad_topical_query: str
|
| 365 |
+
specific_detail_question: str
|
| 366 |
+
specific_detail_query: str
|
| 367 |
+
visual_element_question: str
|
| 368 |
+
visual_element_query: str
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
def get_retrieval_prompt() -> Tuple[str, GeneratedQueries]:
|
| 372 |
+
prompt = (
|
| 373 |
+
prompt
|
| 374 |
+
) = """You are an investor, stock analyst and financial expert. You will be presented an image of a document page from a report published by the Norwegian Government Pension Fund Global (GPFG). The report may be annual or quarterly reports, or policy reports, on topics such as responsible investment, risk etc.
|
| 375 |
+
Your task is to generate retrieval queries and questions that you would use to retrieve this document (or ask based on this document) in a large corpus.
|
| 376 |
+
Please generate 3 different types of retrieval queries and questions.
|
| 377 |
+
A retrieval query is a keyword based query, made up of 2-5 words, that you would type into a search engine to find this document.
|
| 378 |
+
A question is a natural language question that you would ask, for which the document contains the answer.
|
| 379 |
+
The queries should be of the following types:
|
| 380 |
+
1. A broad topical query: This should cover the main subject of the document.
|
| 381 |
+
2. A specific detail query: This should cover a specific detail or aspect of the document.
|
| 382 |
+
3. A visual element query: This should cover a visual element of the document, such as a chart, graph, or image.
|
| 383 |
+
|
| 384 |
+
Important guidelines:
|
| 385 |
+
- Ensure the queries are relevant for retrieval tasks, not just describing the page content.
|
| 386 |
+
- Use a fact-based natural language style for the questions.
|
| 387 |
+
- Frame the queries as if someone is searching for this document in a large corpus.
|
| 388 |
+
- Make the queries diverse and representative of different search strategies.
|
| 389 |
+
|
| 390 |
+
Format your response as a JSON object with the structure of the following example:
|
| 391 |
+
{
|
| 392 |
+
"broad_topical_question": "What was the Responsible Investment Policy in 2019?",
|
| 393 |
+
"broad_topical_query": "responsible investment policy 2019",
|
| 394 |
+
"specific_detail_question": "What is the percentage of investments in renewable energy?",
|
| 395 |
+
"specific_detail_query": "renewable energy investments percentage",
|
| 396 |
+
"visual_element_question": "What is the trend of total holding value over time?",
|
| 397 |
+
"visual_element_query": "total holding value trend"
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
If there are no relevant visual elements, provide an empty string for the visual element question and query.
|
| 401 |
+
Here is the document image to analyze:
|
| 402 |
+
Generate the queries based on this image and provide the response in the specified JSON format.
|
| 403 |
+
Only return JSON. Don't return any extra explanation text. """
|
| 404 |
+
|
| 405 |
+
return prompt, GeneratedQueries
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
prompt_text, pydantic_model = get_retrieval_prompt()
|
| 409 |
+
|
| 410 |
+
# +
|
| 411 |
+
gemini_model = genai.GenerativeModel("gemini-1.5-flash-8b")
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
def generate_queries(image, prompt_text, pydantic_model):
|
| 415 |
+
try:
|
| 416 |
+
response = gemini_model.generate_content(
|
| 417 |
+
[image, "\n\n", prompt_text],
|
| 418 |
+
generation_config=genai.GenerationConfig(
|
| 419 |
+
response_mime_type="application/json",
|
| 420 |
+
response_schema=pydantic_model,
|
| 421 |
+
),
|
| 422 |
+
)
|
| 423 |
+
queries = json.loads(response.text)
|
| 424 |
+
except Exception as _e:
|
| 425 |
+
queries = {
|
| 426 |
+
"broad_topical_question": "",
|
| 427 |
+
"broad_topical_query": "",
|
| 428 |
+
"specific_detail_question": "",
|
| 429 |
+
"specific_detail_query": "",
|
| 430 |
+
"visual_element_question": "",
|
| 431 |
+
"visual_element_query": "",
|
| 432 |
+
}
|
| 433 |
+
return queries
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
# -
|
| 437 |
+
|
| 438 |
+
for pdf in tqdm(pdf_pages):
|
| 439 |
+
image = pdf.get("image")
|
| 440 |
+
pdf["queries"] = generate_queries(image, prompt_text, pydantic_model)
|
| 441 |
+
|
| 442 |
+
pdf_pages[46]["image"]
|
| 443 |
+
|
| 444 |
+
pdf_pages[46]["queries"]
|
| 445 |
+
|
| 446 |
+
# +
|
| 447 |
+
# Generate queries async - keeping for now as we probably need when applying to the full dataset
|
| 448 |
+
# import asyncio
|
| 449 |
+
# from tenacity import retry, stop_after_attempt, wait_exponential
|
| 450 |
+
# import google.generativeai as genai
|
| 451 |
+
# from tqdm.asyncio import tqdm_asyncio
|
| 452 |
+
|
| 453 |
+
# max_in_flight = 200 # Maximum number of concurrent requests
|
| 454 |
+
|
| 455 |
+
|
| 456 |
+
# async def generate_queries_for_image_async(model, image, semaphore):
|
| 457 |
+
# @retry(stop=stop_after_attempt(3), wait=wait_exponential(), reraise=True)
|
| 458 |
+
# async def _generate():
|
| 459 |
+
# async with semaphore:
|
| 460 |
+
# result = await model.generate_content_async(
|
| 461 |
+
# [image, "\n\n", prompt_text],
|
| 462 |
+
# generation_config=genai.GenerationConfig(
|
| 463 |
+
# response_mime_type="application/json",
|
| 464 |
+
# response_schema=pydantic_model,
|
| 465 |
+
# ),
|
| 466 |
+
# )
|
| 467 |
+
# return json.loads(result.text)
|
| 468 |
+
|
| 469 |
+
# try:
|
| 470 |
+
# return await _generate()
|
| 471 |
+
# except Exception as e:
|
| 472 |
+
# print(f"Error generating queries for image: {e}")
|
| 473 |
+
# return None # Return None or handle as needed
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
# async def enrich_pdfs():
|
| 477 |
+
# gemini_model = genai.GenerativeModel("gemini-1.5-flash-8b")
|
| 478 |
+
# semaphore = asyncio.Semaphore(max_in_flight)
|
| 479 |
+
# tasks = []
|
| 480 |
+
# for pdf in pdf_pages:
|
| 481 |
+
# pdf["queries"] = []
|
| 482 |
+
# image = pdf.get("image")
|
| 483 |
+
# if image:
|
| 484 |
+
# task = generate_queries_for_image_async(gemini_model, image, semaphore)
|
| 485 |
+
# tasks.append((pdf, task))
|
| 486 |
+
|
| 487 |
+
# # Run the tasks concurrently using asyncio.gather()
|
| 488 |
+
# for pdf, task in tqdm_asyncio(tasks):
|
| 489 |
+
# result = await task
|
| 490 |
+
# if result:
|
| 491 |
+
# pdf["queries"] = result
|
| 492 |
+
# return pdf_pages
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
# pdf_pages = asyncio.run(enrich_pdfs())
|
| 496 |
+
|
| 497 |
+
# +
|
| 498 |
+
# write title, url, page_no, text, queries, not image to JSON
|
| 499 |
+
os.makedirs("output", exist_ok=True)
|
| 500 |
+
with open("output/pdf_pages.json", "w") as f:
|
| 501 |
+
to_write = [{k: v for k, v in pdf.items() if k != "image"} for pdf in pdf_pages]
|
| 502 |
+
json.dump(to_write, f, indent=2)
|
| 503 |
+
|
| 504 |
+
# with open("pdfs/pdf_pages.json", "r") as f:
|
| 505 |
+
# saved_pdf_pages = json.load(f)
|
| 506 |
+
# for pdf, saved_pdf in zip(pdf_pages, saved_pdf_pages):
|
| 507 |
+
# pdf.update(saved_pdf)
|
| 508 |
+
# -
|
| 509 |
+
|
| 510 |
+
# ## 4. Generate embeddings
|
| 511 |
+
#
|
| 512 |
+
# Now that we have the queries, we can use the ColPali model to generate embeddings for each page image.
|
| 513 |
+
#
|
| 514 |
+
|
| 515 |
+
|
| 516 |
+
def generate_embeddings(images, model, processor, batch_size=2) -> np.ndarray:
|
| 517 |
+
"""
|
| 518 |
+
Generate embeddings for a list of images.
|
| 519 |
+
Move to CPU only once per batch.
|
| 520 |
+
|
| 521 |
+
Args:
|
| 522 |
+
images (List[PIL.Image]): List of PIL images.
|
| 523 |
+
model (nn.Module): The model to generate embeddings.
|
| 524 |
+
processor: The processor to preprocess images.
|
| 525 |
+
batch_size (int, optional): Batch size for processing. Defaults to 64.
|
| 526 |
+
|
| 527 |
+
Returns:
|
| 528 |
+
np.ndarray: Embeddings for the images, shape
|
| 529 |
+
(len(images), processor.max_patch_length (1030 for ColPali), model.config.hidden_size (Patch embedding dimension - 128 for ColPali)).
|
| 530 |
+
"""
|
| 531 |
+
embeddings_list = []
|
| 532 |
+
|
| 533 |
+
def collate_fn(batch):
|
| 534 |
+
# Batch is a list of images
|
| 535 |
+
return processor.process_images(batch) # Should return a dict of tensors
|
| 536 |
+
|
| 537 |
+
dataloader = DataLoader(
|
| 538 |
+
images,
|
| 539 |
+
shuffle=False,
|
| 540 |
+
collate_fn=collate_fn,
|
| 541 |
+
)
|
| 542 |
+
|
| 543 |
+
for batch_doc in tqdm(dataloader, desc="Generating embeddings"):
|
| 544 |
+
with torch.no_grad():
|
| 545 |
+
# Move batch to the device
|
| 546 |
+
batch_doc = {k: v.to(model.device) for k, v in batch_doc.items()}
|
| 547 |
+
embeddings_batch = model(**batch_doc)
|
| 548 |
+
embeddings_list.append(torch.unbind(embeddings_batch.to("cpu"), dim=0))
|
| 549 |
+
# Concatenate all embeddings and create a numpy array
|
| 550 |
+
all_embeddings = np.concatenate(embeddings_list, axis=0)
|
| 551 |
+
return all_embeddings
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
# Generate embeddings for all images
|
| 555 |
+
images = [pdf["image"] for pdf in pdf_pages]
|
| 556 |
+
embeddings = generate_embeddings(images, model, processor)
|
| 557 |
+
|
| 558 |
+
embeddings.shape
|
| 559 |
+
|
| 560 |
+
# ## 5. Prepare Data on Vespa Format
|
| 561 |
+
#
|
| 562 |
+
# Now, that we have all the data we need, all that remains is to make sure it is in the right format for Vespa.
|
| 563 |
+
#
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
def float_to_binary_embedding(float_query_embedding: dict) -> dict:
|
| 567 |
+
"""Utility function to convert float query embeddings to binary query embeddings."""
|
| 568 |
+
binary_query_embeddings = {}
|
| 569 |
+
for k, v in float_query_embedding.items():
|
| 570 |
+
binary_vector = (
|
| 571 |
+
np.packbits(np.where(np.array(v) > 0, 1, 0)).astype(np.int8).tolist()
|
| 572 |
+
)
|
| 573 |
+
binary_query_embeddings[k] = binary_vector
|
| 574 |
+
return binary_query_embeddings
|
| 575 |
+
|
| 576 |
+
|
| 577 |
+
vespa_feed = []
|
| 578 |
+
for pdf, embedding in zip(pdf_pages, embeddings):
|
| 579 |
+
url = pdf["url"]
|
| 580 |
+
year = pdf["year"]
|
| 581 |
+
title = pdf["title"]
|
| 582 |
+
image = pdf["image"]
|
| 583 |
+
text = pdf.get("text", "")
|
| 584 |
+
page_no = pdf["page_no"]
|
| 585 |
+
query_dict = pdf["queries"]
|
| 586 |
+
questions = [v for k, v in query_dict.items() if "question" in k and v]
|
| 587 |
+
queries = [v for k, v in query_dict.items() if "query" in k and v]
|
| 588 |
+
base_64_image = get_base64_image(
|
| 589 |
+
scale_image(image, 32), add_url_prefix=False
|
| 590 |
+
) # Scaled down image to return fast on search (~1kb)
|
| 591 |
+
base_64_full_image = get_base64_image(image, add_url_prefix=False)
|
| 592 |
+
embedding_dict = {k: v for k, v in enumerate(embedding)}
|
| 593 |
+
binary_embedding = float_to_binary_embedding(embedding_dict)
|
| 594 |
+
# id_hash should be md5 hash of url and page_number
|
| 595 |
+
id_hash = hashlib.md5(f"{url}_{page_no}".encode()).hexdigest()
|
| 596 |
+
page = {
|
| 597 |
+
"id": id_hash,
|
| 598 |
+
"fields": {
|
| 599 |
+
"id": id_hash,
|
| 600 |
+
"url": url,
|
| 601 |
+
"title": title,
|
| 602 |
+
"year": year,
|
| 603 |
+
"page_number": page_no,
|
| 604 |
+
"blur_image": base_64_image,
|
| 605 |
+
"full_image": base_64_full_image,
|
| 606 |
+
"text": text,
|
| 607 |
+
"embedding": binary_embedding,
|
| 608 |
+
"queries": queries,
|
| 609 |
+
"questions": questions,
|
| 610 |
+
},
|
| 611 |
+
}
|
| 612 |
+
vespa_feed.append(page)
|
| 613 |
+
|
| 614 |
+
# +
|
| 615 |
+
# We will prepare the Vespa feed data, including the embeddings and the generated queries
|
| 616 |
+
|
| 617 |
+
|
| 618 |
+
# Save vespa_feed to vespa_feed.json
|
| 619 |
+
with open("output/vespa_feed.json", "w") as f:
|
| 620 |
+
vespa_feed_to_save = []
|
| 621 |
+
for page in vespa_feed:
|
| 622 |
+
document_id = page["id"]
|
| 623 |
+
put_id = f"id:{VESPA_APPLICATION_NAME}:{VESPA_SCHEMA_NAME}::{document_id}"
|
| 624 |
+
vespa_feed_to_save.append({"put": put_id, "fields": page["fields"]})
|
| 625 |
+
json.dump(vespa_feed_to_save, f)
|
| 626 |
+
|
| 627 |
+
# +
|
| 628 |
+
# import json
|
| 629 |
+
|
| 630 |
+
# with open("output/vespa_feed.json", "r") as f:
|
| 631 |
+
# vespa_feed = json.load(f)
|
| 632 |
+
# -
|
| 633 |
+
|
| 634 |
+
len(vespa_feed)
|
| 635 |
+
|
| 636 |
+
# ## 5. Prepare Vespa Application
|
| 637 |
+
#
|
| 638 |
+
|
| 639 |
+
# +
|
| 640 |
+
# Define the Vespa schema
|
| 641 |
+
colpali_schema = Schema(
|
| 642 |
+
name=VESPA_SCHEMA_NAME,
|
| 643 |
+
document=Document(
|
| 644 |
+
fields=[
|
| 645 |
+
Field(
|
| 646 |
+
name="id",
|
| 647 |
+
type="string",
|
| 648 |
+
indexing=["summary", "index"],
|
| 649 |
+
match=["word"],
|
| 650 |
+
),
|
| 651 |
+
Field(name="url", type="string", indexing=["summary", "index"]),
|
| 652 |
+
Field(name="year", type="int", indexing=["summary", "attribute"]),
|
| 653 |
+
Field(
|
| 654 |
+
name="title",
|
| 655 |
+
type="string",
|
| 656 |
+
indexing=["summary", "index"],
|
| 657 |
+
match=["text"],
|
| 658 |
+
index="enable-bm25",
|
| 659 |
+
),
|
| 660 |
+
Field(name="page_number", type="int", indexing=["summary", "attribute"]),
|
| 661 |
+
Field(name="blur_image", type="raw", indexing=["summary"]),
|
| 662 |
+
Field(name="full_image", type="raw", indexing=["summary"]),
|
| 663 |
+
Field(
|
| 664 |
+
name="text",
|
| 665 |
+
type="string",
|
| 666 |
+
indexing=["summary", "index"],
|
| 667 |
+
match=["text"],
|
| 668 |
+
index="enable-bm25",
|
| 669 |
+
),
|
| 670 |
+
Field(
|
| 671 |
+
name="embedding",
|
| 672 |
+
type="tensor<int8>(patch{}, v[16])",
|
| 673 |
+
indexing=[
|
| 674 |
+
"attribute",
|
| 675 |
+
"index",
|
| 676 |
+
],
|
| 677 |
+
ann=HNSW(
|
| 678 |
+
distance_metric="hamming",
|
| 679 |
+
max_links_per_node=32,
|
| 680 |
+
neighbors_to_explore_at_insert=400,
|
| 681 |
+
),
|
| 682 |
+
),
|
| 683 |
+
Field(
|
| 684 |
+
name="questions",
|
| 685 |
+
type="array<string>",
|
| 686 |
+
indexing=["summary", "attribute"],
|
| 687 |
+
summary=Summary(fields=["matched-elements-only"]),
|
| 688 |
+
),
|
| 689 |
+
Field(
|
| 690 |
+
name="queries",
|
| 691 |
+
type="array<string>",
|
| 692 |
+
indexing=["summary", "attribute"],
|
| 693 |
+
summary=Summary(fields=["matched-elements-only"]),
|
| 694 |
+
),
|
| 695 |
+
]
|
| 696 |
+
),
|
| 697 |
+
fieldsets=[
|
| 698 |
+
FieldSet(
|
| 699 |
+
name="default",
|
| 700 |
+
fields=["title", "text"],
|
| 701 |
+
),
|
| 702 |
+
],
|
| 703 |
+
document_summaries=[
|
| 704 |
+
DocumentSummary(
|
| 705 |
+
name="default",
|
| 706 |
+
summary_fields=[
|
| 707 |
+
Summary(
|
| 708 |
+
name="text",
|
| 709 |
+
fields=[("bolding", "on")],
|
| 710 |
+
),
|
| 711 |
+
Summary(
|
| 712 |
+
name="snippet",
|
| 713 |
+
fields=[("source", "text"), "dynamic"],
|
| 714 |
+
),
|
| 715 |
+
],
|
| 716 |
+
from_disk=True,
|
| 717 |
+
),
|
| 718 |
+
DocumentSummary(
|
| 719 |
+
name="suggestions",
|
| 720 |
+
summary_fields=[
|
| 721 |
+
Summary(name="questions"),
|
| 722 |
+
],
|
| 723 |
+
from_disk=True,
|
| 724 |
+
),
|
| 725 |
+
],
|
| 726 |
+
)
|
| 727 |
+
|
| 728 |
+
# Define similarity functions used in all rank profiles
|
| 729 |
+
mapfunctions = [
|
| 730 |
+
Function(
|
| 731 |
+
name="similarities", # computes similarity scores between each query token and image patch
|
| 732 |
+
expression="""
|
| 733 |
+
sum(
|
| 734 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 735 |
+
)
|
| 736 |
+
""",
|
| 737 |
+
),
|
| 738 |
+
Function(
|
| 739 |
+
name="normalized", # normalizes the similarity scores to [-1, 1]
|
| 740 |
+
expression="""
|
| 741 |
+
(similarities - reduce(similarities, min)) / (reduce((similarities - reduce(similarities, min)), max)) * 2 - 1
|
| 742 |
+
""",
|
| 743 |
+
),
|
| 744 |
+
Function(
|
| 745 |
+
name="quantized", # quantizes the normalized similarity scores to signed 8-bit integers [-128, 127]
|
| 746 |
+
expression="""
|
| 747 |
+
cell_cast(normalized * 127.999, int8)
|
| 748 |
+
""",
|
| 749 |
+
),
|
| 750 |
+
]
|
| 751 |
+
|
| 752 |
+
# Define the 'bm25' rank profile
|
| 753 |
+
bm25 = RankProfile(
|
| 754 |
+
name="bm25",
|
| 755 |
+
inputs=[("query(qt)", "tensor<float>(querytoken{}, v[128])")],
|
| 756 |
+
first_phase="bm25(title) + bm25(text)",
|
| 757 |
+
functions=mapfunctions,
|
| 758 |
+
)
|
| 759 |
+
|
| 760 |
+
|
| 761 |
+
# A function to create an inherited rank profile which also returns quantized similarity scores
|
| 762 |
+
def with_quantized_similarity(rank_profile: RankProfile) -> RankProfile:
|
| 763 |
+
return RankProfile(
|
| 764 |
+
name=f"{rank_profile.name}_sim",
|
| 765 |
+
first_phase=rank_profile.first_phase,
|
| 766 |
+
inherits=rank_profile.name,
|
| 767 |
+
summary_features=["quantized"],
|
| 768 |
+
)
|
| 769 |
+
|
| 770 |
+
|
| 771 |
+
colpali_schema.add_rank_profile(bm25)
|
| 772 |
+
colpali_schema.add_rank_profile(with_quantized_similarity(bm25))
|
| 773 |
+
|
| 774 |
+
|
| 775 |
+
# Update the 'colpali' rank profile
|
| 776 |
+
input_query_tensors = []
|
| 777 |
+
MAX_QUERY_TERMS = 64
|
| 778 |
+
for i in range(MAX_QUERY_TERMS):
|
| 779 |
+
input_query_tensors.append((f"query(rq{i})", "tensor<int8>(v[16])"))
|
| 780 |
+
|
| 781 |
+
input_query_tensors.extend(
|
| 782 |
+
[
|
| 783 |
+
("query(qt)", "tensor<float>(querytoken{}, v[128])"),
|
| 784 |
+
("query(qtb)", "tensor<int8>(querytoken{}, v[16])"),
|
| 785 |
+
]
|
| 786 |
+
)
|
| 787 |
+
|
| 788 |
+
colpali = RankProfile(
|
| 789 |
+
name="colpali",
|
| 790 |
+
inputs=input_query_tensors,
|
| 791 |
+
first_phase="max_sim_binary",
|
| 792 |
+
second_phase=SecondPhaseRanking(expression="max_sim", rerank_count=10),
|
| 793 |
+
functions=mapfunctions
|
| 794 |
+
+ [
|
| 795 |
+
Function(
|
| 796 |
+
name="max_sim",
|
| 797 |
+
expression="""
|
| 798 |
+
sum(
|
| 799 |
+
reduce(
|
| 800 |
+
sum(
|
| 801 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 802 |
+
),
|
| 803 |
+
max, patch
|
| 804 |
+
),
|
| 805 |
+
querytoken
|
| 806 |
+
)
|
| 807 |
+
""",
|
| 808 |
+
),
|
| 809 |
+
Function(
|
| 810 |
+
name="max_sim_binary",
|
| 811 |
+
expression="""
|
| 812 |
+
sum(
|
| 813 |
+
reduce(
|
| 814 |
+
1 / (1 + sum(
|
| 815 |
+
hamming(query(qtb), attribute(embedding)), v)
|
| 816 |
+
),
|
| 817 |
+
max, patch
|
| 818 |
+
),
|
| 819 |
+
querytoken
|
| 820 |
+
)
|
| 821 |
+
""",
|
| 822 |
+
),
|
| 823 |
+
],
|
| 824 |
+
)
|
| 825 |
+
colpali_schema.add_rank_profile(colpali)
|
| 826 |
+
colpali_schema.add_rank_profile(with_quantized_similarity(colpali))
|
| 827 |
+
|
| 828 |
+
# Update the 'hybrid' rank profile
|
| 829 |
+
hybrid = RankProfile(
|
| 830 |
+
name="hybrid",
|
| 831 |
+
inputs=input_query_tensors,
|
| 832 |
+
first_phase="max_sim_binary",
|
| 833 |
+
second_phase=SecondPhaseRanking(
|
| 834 |
+
expression="max_sim + 2 * (bm25(text) + bm25(title))", rerank_count=10
|
| 835 |
+
),
|
| 836 |
+
functions=mapfunctions
|
| 837 |
+
+ [
|
| 838 |
+
Function(
|
| 839 |
+
name="max_sim",
|
| 840 |
+
expression="""
|
| 841 |
+
sum(
|
| 842 |
+
reduce(
|
| 843 |
+
sum(
|
| 844 |
+
query(qt) * unpack_bits(attribute(embedding)), v
|
| 845 |
+
),
|
| 846 |
+
max, patch
|
| 847 |
+
),
|
| 848 |
+
querytoken
|
| 849 |
+
)
|
| 850 |
+
""",
|
| 851 |
+
),
|
| 852 |
+
Function(
|
| 853 |
+
name="max_sim_binary",
|
| 854 |
+
expression="""
|
| 855 |
+
sum(
|
| 856 |
+
reduce(
|
| 857 |
+
1 / (1 + sum(
|
| 858 |
+
hamming(query(qtb), attribute(embedding)), v)
|
| 859 |
+
),
|
| 860 |
+
max, patch
|
| 861 |
+
),
|
| 862 |
+
querytoken
|
| 863 |
+
)
|
| 864 |
+
""",
|
| 865 |
+
),
|
| 866 |
+
],
|
| 867 |
+
)
|
| 868 |
+
colpali_schema.add_rank_profile(hybrid)
|
| 869 |
+
colpali_schema.add_rank_profile(with_quantized_similarity(hybrid))
|
| 870 |
+
|
| 871 |
+
# +
|
| 872 |
+
from vespa.configuration.services import (
|
| 873 |
+
services,
|
| 874 |
+
container,
|
| 875 |
+
search,
|
| 876 |
+
document_api,
|
| 877 |
+
document_processing,
|
| 878 |
+
clients,
|
| 879 |
+
client,
|
| 880 |
+
config,
|
| 881 |
+
content,
|
| 882 |
+
redundancy,
|
| 883 |
+
documents,
|
| 884 |
+
node,
|
| 885 |
+
certificate,
|
| 886 |
+
token,
|
| 887 |
+
document,
|
| 888 |
+
nodes,
|
| 889 |
+
)
|
| 890 |
+
from vespa.configuration.vt import vt
|
| 891 |
+
from vespa.package import ServicesConfiguration
|
| 892 |
+
|
| 893 |
+
service_config = ServicesConfiguration(
|
| 894 |
+
application_name=VESPA_APPLICATION_NAME,
|
| 895 |
+
services_config=services(
|
| 896 |
+
container(
|
| 897 |
+
search(),
|
| 898 |
+
document_api(),
|
| 899 |
+
document_processing(),
|
| 900 |
+
clients(
|
| 901 |
+
client(
|
| 902 |
+
certificate(file="security/clients.pem"),
|
| 903 |
+
id="mtls",
|
| 904 |
+
permissions="read,write",
|
| 905 |
+
),
|
| 906 |
+
client(
|
| 907 |
+
token(id=f"{VESPA_TOKEN_ID_WRITE}"),
|
| 908 |
+
id="token_write",
|
| 909 |
+
permissions="read,write",
|
| 910 |
+
),
|
| 911 |
+
),
|
| 912 |
+
config(
|
| 913 |
+
vt("tag")(
|
| 914 |
+
vt("bold")(
|
| 915 |
+
vt("open", "<strong>"),
|
| 916 |
+
vt("close", "</strong>"),
|
| 917 |
+
),
|
| 918 |
+
vt("separator", "..."),
|
| 919 |
+
),
|
| 920 |
+
name="container.qr-searchers",
|
| 921 |
+
),
|
| 922 |
+
id=f"{VESPA_APPLICATION_NAME}_container",
|
| 923 |
+
version="1.0",
|
| 924 |
+
),
|
| 925 |
+
content(
|
| 926 |
+
redundancy("1"),
|
| 927 |
+
documents(document(type="pdf_page", mode="index")),
|
| 928 |
+
nodes(node(distribution_key="0", hostalias="node1")),
|
| 929 |
+
config(
|
| 930 |
+
vt("max_matches", "2", replace_underscores=False),
|
| 931 |
+
vt("length", "1000"),
|
| 932 |
+
vt("surround_max", "500", replace_underscores=False),
|
| 933 |
+
vt("min_length", "300", replace_underscores=False),
|
| 934 |
+
name="vespa.config.search.summary.juniperrc",
|
| 935 |
+
),
|
| 936 |
+
id=f"{VESPA_APPLICATION_NAME}_content",
|
| 937 |
+
version="1.0",
|
| 938 |
+
),
|
| 939 |
+
version="1.0",
|
| 940 |
+
),
|
| 941 |
+
)
|
| 942 |
+
# -
|
| 943 |
+
|
| 944 |
+
# Create the Vespa application package
|
| 945 |
+
vespa_application_package = ApplicationPackage(
|
| 946 |
+
name=VESPA_APPLICATION_NAME,
|
| 947 |
+
schema=[colpali_schema],
|
| 948 |
+
services_config=service_config,
|
| 949 |
+
)
|
| 950 |
+
|
| 951 |
+
# ## 6. Deploy Vespa Application
|
| 952 |
+
#
|
| 953 |
+
|
| 954 |
+
VESPA_TEAM_API_KEY = os.getenv("VESPA_TEAM_API_KEY") or input(
|
| 955 |
+
"Enter Vespa team API key: "
|
| 956 |
+
)
|
| 957 |
+
|
| 958 |
+
# +
|
| 959 |
+
vespa_cloud = VespaCloud(
|
| 960 |
+
tenant=VESPA_TENANT_NAME,
|
| 961 |
+
application=VESPA_APPLICATION_NAME,
|
| 962 |
+
key_content=VESPA_TEAM_API_KEY,
|
| 963 |
+
application_package=vespa_application_package,
|
| 964 |
+
)
|
| 965 |
+
|
| 966 |
+
# Deploy the application
|
| 967 |
+
vespa_cloud.deploy()
|
| 968 |
+
|
| 969 |
+
# Output the endpoint URL
|
| 970 |
+
endpoint_url = vespa_cloud.get_token_endpoint()
|
| 971 |
+
print(f"Application deployed. Token endpoint URL: {endpoint_url}")
|
| 972 |
+
# -
|
| 973 |
+
|
| 974 |
+
# Make sure to take note of the token endpoint_url.
|
| 975 |
+
# You need to put this in your `.env` file - `VESPA_APP_URL=https://abcd.vespa-app.cloud` - to access the Vespa application from your web application.
|
| 976 |
+
#
|
| 977 |
+
|
| 978 |
+
# ## 8. Feed Data to Vespa
|
| 979 |
+
#
|
| 980 |
+
|
| 981 |
+
# Instantiate Vespa connection using token
|
| 982 |
+
app = Vespa(url=endpoint_url, vespa_cloud_secret_token=VESPA_CLOUD_SECRET_TOKEN)
|
| 983 |
+
app.get_application_status()
|
| 984 |
+
|
| 985 |
+
|
| 986 |
+
# +
|
| 987 |
+
def callback(response: VespaResponse, id: str):
|
| 988 |
+
if not response.is_successful():
|
| 989 |
+
print(
|
| 990 |
+
f"Failed to feed document {id} with status code {response.status_code}: Reason {response.get_json()}"
|
| 991 |
+
)
|
| 992 |
+
|
| 993 |
+
|
| 994 |
+
# Feed data into Vespa asynchronously
|
| 995 |
+
app.feed_async_iterable(vespa_feed, schema=VESPA_SCHEMA_NAME, callback=callback)
|
pyproject.toml
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "visual-retrieval-colpali"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Visual retrieval with ColPali"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
requires-python = ">=3.10, <3.12"
|
| 7 |
+
license = { text = "Apache-2.0" }
|
| 8 |
+
dependencies = [
|
| 9 |
+
"python-fasthtml",
|
| 10 |
+
"huggingface-hub",
|
| 11 |
+
"pyvespa>=0.50.0",
|
| 12 |
+
"vespacli",
|
| 13 |
+
"torch",
|
| 14 |
+
"vidore-benchmark[interpretability]>=4.0.0,<5.0.0",
|
| 15 |
+
"colpali-engine",
|
| 16 |
+
"einops",
|
| 17 |
+
"pypdf",
|
| 18 |
+
"setuptools",
|
| 19 |
+
"python-dotenv",
|
| 20 |
+
"shad4fast>=1.2.1",
|
| 21 |
+
"google-generativeai>=0.7.2",
|
| 22 |
+
"spacy",
|
| 23 |
+
"pip",
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
# dev-dependencies
|
| 27 |
+
[project.optional-dependencies]
|
| 28 |
+
dev = ["ruff", "python-dotenv", "huggingface_hub[cli]"]
|
| 29 |
+
feed = [
|
| 30 |
+
"ipykernel",
|
| 31 |
+
"jupytext",
|
| 32 |
+
"pydantic",
|
| 33 |
+
"beautifulsoup4",
|
| 34 |
+
"pdf2image",
|
| 35 |
+
"google-generativeai",
|
| 36 |
+
]
|
| 37 |
+
[tool.ruff]
|
| 38 |
+
# Exclude a variety of commonly ignored directories.
|
| 39 |
+
exclude = [
|
| 40 |
+
".bzr",
|
| 41 |
+
".direnv",
|
| 42 |
+
".eggs",
|
| 43 |
+
".git",
|
| 44 |
+
".git-rewrite",
|
| 45 |
+
".hg",
|
| 46 |
+
".ipynb_checkpoints",
|
| 47 |
+
".mypy_cache",
|
| 48 |
+
".nox",
|
| 49 |
+
".pants.d",
|
| 50 |
+
".pyenv",
|
| 51 |
+
".pytest_cache",
|
| 52 |
+
".pytype",
|
| 53 |
+
".ruff_cache",
|
| 54 |
+
".svn",
|
| 55 |
+
".tox",
|
| 56 |
+
".venv",
|
| 57 |
+
".vscode",
|
| 58 |
+
"__pypackages__",
|
| 59 |
+
"_build",
|
| 60 |
+
"buck-out",
|
| 61 |
+
"build",
|
| 62 |
+
"dist",
|
| 63 |
+
"node_modules",
|
| 64 |
+
"site-packages",
|
| 65 |
+
"venv",
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
# Same as Black.
|
| 69 |
+
line-length = 88
|
| 70 |
+
indent-width = 4
|
| 71 |
+
|
| 72 |
+
# Assume Python 3.8
|
| 73 |
+
target-version = "py38"
|
| 74 |
+
|
| 75 |
+
[tool.ruff.lint]
|
| 76 |
+
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
| 77 |
+
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
|
| 78 |
+
# McCabe complexity (`C901`) by default.
|
| 79 |
+
select = ["E4", "E7", "E9", "F"]
|
| 80 |
+
ignore = []
|
| 81 |
+
|
| 82 |
+
# Allow fix for all enabled rules (when `--fix`) is provided.
|
| 83 |
+
fixable = ["ALL"]
|
| 84 |
+
unfixable = []
|
| 85 |
+
|
| 86 |
+
# Allow unused variables when underscore-prefixed.
|
| 87 |
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
| 88 |
+
|
| 89 |
+
[tool.ruff.format]
|
| 90 |
+
# Like Black, use double quotes for strings.
|
| 91 |
+
quote-style = "double"
|
| 92 |
+
|
| 93 |
+
# Like Black, indent with spaces, rather than tabs.
|
| 94 |
+
indent-style = "space"
|
| 95 |
+
|
| 96 |
+
# Like Black, respect magic trailing commas.
|
| 97 |
+
skip-magic-trailing-comma = false
|
| 98 |
+
|
| 99 |
+
# Like Black, automatically detect the appropriate line ending.
|
| 100 |
+
line-ending = "auto"
|
| 101 |
+
|
| 102 |
+
# Enable auto-formatting of code examples in docstrings. Markdown,
|
| 103 |
+
# reStructuredText code/literal blocks and doctests are all supported.
|
| 104 |
+
#
|
| 105 |
+
# This is currently disabled by default, but it is planned for this
|
| 106 |
+
# to be opt-out in the future.
|
| 107 |
+
docstring-code-format = false
|
| 108 |
+
|
| 109 |
+
# Set the line length limit used when formatting code snippets in
|
| 110 |
+
# docstrings.
|
| 111 |
+
#
|
| 112 |
+
# This only has an effect when the `docstring-code-format` setting is
|
| 113 |
+
# enabled.
|
| 114 |
+
docstring-code-line-length = "dynamic"
|
src/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: ColPali 🤝 Vespa - Visual Retrieval
|
| 3 |
+
short_description: Visual Retrieval with ColPali and Vespa
|
| 4 |
+
emoji: 👀
|
| 5 |
+
colorFrom: purple
|
| 6 |
+
colorTo: blue
|
| 7 |
+
sdk: gradio
|
| 8 |
+
sdk_version: 4.44.0
|
| 9 |
+
app_file: main.py
|
| 10 |
+
pinned: false
|
| 11 |
+
license: apache-2.0
|
| 12 |
+
suggested_hardware: t4-small
|
| 13 |
+
models:
|
| 14 |
+
- vidore/colpaligemma-3b-pt-448-base
|
| 15 |
+
- vidore/colpali-v1.2
|
| 16 |
+
preload_from_hub:
|
| 17 |
+
- vidore/colpaligemma-3b-pt-448-base config.json,model-00001-of-00002.safetensors,model-00002-of-00002.safetensors,model.safetensors.index.json,preprocessor_config.json,special_tokens_map.json,tokenizer.json,tokenizer_config.json 12c59eb7e23bc4c26876f7be7c17760d5d3a1ffa
|
| 18 |
+
- vidore/colpali-v1.2 adapter_config.json,adapter_model.safetensors,preprocessor_config.json,special_tokens_map.json,tokenizer.json,tokenizer_config.json 9912ce6f8a462d8cf2269f5606eabbd2784e764f
|
| 19 |
+
---
|
src/backend/__init__.py
ADDED
|
File without changes
|
src/backend/cache.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import OrderedDict
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# Initialize LRU Cache
|
| 5 |
+
class LRUCache:
|
| 6 |
+
def __init__(self, max_size=20):
|
| 7 |
+
self.max_size = max_size
|
| 8 |
+
self.cache = OrderedDict()
|
| 9 |
+
|
| 10 |
+
def get(self, key):
|
| 11 |
+
if key in self.cache:
|
| 12 |
+
self.cache.move_to_end(key)
|
| 13 |
+
return self.cache[key]
|
| 14 |
+
return None
|
| 15 |
+
|
| 16 |
+
def set(self, key, value):
|
| 17 |
+
if key in self.cache:
|
| 18 |
+
self.cache.move_to_end(key)
|
| 19 |
+
else:
|
| 20 |
+
if len(self.cache) >= self.max_size:
|
| 21 |
+
self.cache.popitem(last=False)
|
| 22 |
+
self.cache[key] = value
|
| 23 |
+
|
| 24 |
+
def delete(self, key):
|
| 25 |
+
if key in self.cache:
|
| 26 |
+
del self.cache[key]
|
src/backend/colpali.py
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from PIL import Image
|
| 3 |
+
import numpy as np
|
| 4 |
+
from typing import Generator, Tuple, List, Union, Dict
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
import base64
|
| 7 |
+
from io import BytesIO
|
| 8 |
+
import re
|
| 9 |
+
import io
|
| 10 |
+
import matplotlib.cm as cm
|
| 11 |
+
|
| 12 |
+
from colpali_engine.models import ColPali, ColPaliProcessor
|
| 13 |
+
from colpali_engine.utils.torch_utils import get_torch_device
|
| 14 |
+
from vidore_benchmark.interpretability.torch_utils import (
|
| 15 |
+
normalize_similarity_map_per_query_token,
|
| 16 |
+
)
|
| 17 |
+
from functools import lru_cache
|
| 18 |
+
import logging
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class SimMapGenerator:
|
| 22 |
+
"""
|
| 23 |
+
Generates similarity maps based on query embeddings and image patches using the ColPali model.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
colormap = cm.get_cmap("viridis") # Preload colormap for efficiency
|
| 27 |
+
|
| 28 |
+
def __init__(
|
| 29 |
+
self,
|
| 30 |
+
logger: logging.Logger,
|
| 31 |
+
model_name: str = "vidore/colpali-v1.2",
|
| 32 |
+
n_patch: int = 32,
|
| 33 |
+
):
|
| 34 |
+
"""
|
| 35 |
+
Initializes the SimMapGenerator class with a specified model and patch dimension.
|
| 36 |
+
|
| 37 |
+
Args:
|
| 38 |
+
model_name (str): The model name for loading the ColPali model.
|
| 39 |
+
n_patch (int): The number of patches per dimension.
|
| 40 |
+
"""
|
| 41 |
+
self.model_name = model_name
|
| 42 |
+
self.n_patch = n_patch
|
| 43 |
+
self.device = get_torch_device("auto")
|
| 44 |
+
self.logger = logger
|
| 45 |
+
self.logger.info(f"Using device: {self.device}")
|
| 46 |
+
self.model, self.processor = self.load_model()
|
| 47 |
+
|
| 48 |
+
def load_model(self) -> Tuple[ColPali, ColPaliProcessor]:
|
| 49 |
+
"""
|
| 50 |
+
Loads the ColPali model and processor.
|
| 51 |
+
|
| 52 |
+
Returns:
|
| 53 |
+
Tuple[ColPali, ColPaliProcessor]: Loaded model and processor.
|
| 54 |
+
"""
|
| 55 |
+
model = ColPali.from_pretrained(
|
| 56 |
+
self.model_name,
|
| 57 |
+
torch_dtype=torch.bfloat16, # Note that the embeddings created during feed were float32 -> binarized, yet setting this seem to produce the most similar results both locally (mps) and HF (Cuda)
|
| 58 |
+
device_map=self.device,
|
| 59 |
+
).eval()
|
| 60 |
+
|
| 61 |
+
processor = ColPaliProcessor.from_pretrained(self.model_name)
|
| 62 |
+
return model, processor
|
| 63 |
+
|
| 64 |
+
def gen_similarity_maps(
|
| 65 |
+
self,
|
| 66 |
+
query: str,
|
| 67 |
+
query_embs: torch.Tensor,
|
| 68 |
+
token_idx_map: Dict[int, str],
|
| 69 |
+
images: List[Union[Path, str]],
|
| 70 |
+
vespa_sim_maps: List[Dict],
|
| 71 |
+
) -> Generator[Tuple[int, str, str], None, None]:
|
| 72 |
+
"""
|
| 73 |
+
Generates similarity maps for the provided images and query, and returns base64-encoded blended images.
|
| 74 |
+
|
| 75 |
+
Args:
|
| 76 |
+
query (str): The query string.
|
| 77 |
+
query_embs (torch.Tensor): Query embeddings tensor.
|
| 78 |
+
token_idx_map (dict): Mapping from indices to tokens.
|
| 79 |
+
images (List[Union[Path, str]]): List of image paths or base64-encoded strings.
|
| 80 |
+
vespa_sim_maps (List[Dict]): List of Vespa similarity maps.
|
| 81 |
+
|
| 82 |
+
Yields:
|
| 83 |
+
Tuple[int, str, str]: A tuple containing the image index, selected token, and base64-encoded image.
|
| 84 |
+
"""
|
| 85 |
+
processed_images, original_images, original_sizes = [], [], []
|
| 86 |
+
for img in images:
|
| 87 |
+
img_pil = self._load_image(img)
|
| 88 |
+
original_images.append(img_pil.copy())
|
| 89 |
+
original_sizes.append(img_pil.size)
|
| 90 |
+
processed_images.append(img_pil)
|
| 91 |
+
|
| 92 |
+
vespa_sim_map_tensor = self._prepare_similarity_map_tensor(
|
| 93 |
+
query_embs, vespa_sim_maps
|
| 94 |
+
)
|
| 95 |
+
similarity_map_normalized = normalize_similarity_map_per_query_token(
|
| 96 |
+
vespa_sim_map_tensor
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
for idx, img in enumerate(original_images):
|
| 100 |
+
for token_idx, token in token_idx_map.items():
|
| 101 |
+
if self.should_filter_token(token):
|
| 102 |
+
continue
|
| 103 |
+
|
| 104 |
+
sim_map = similarity_map_normalized[idx, token_idx, :, :]
|
| 105 |
+
blended_img_base64 = self._blend_image(
|
| 106 |
+
img, sim_map, original_sizes[idx]
|
| 107 |
+
)
|
| 108 |
+
yield idx, token, token_idx, blended_img_base64
|
| 109 |
+
|
| 110 |
+
def _load_image(self, img: Union[Path, str]) -> Image:
|
| 111 |
+
"""
|
| 112 |
+
Loads an image from a file path or a base64-encoded string.
|
| 113 |
+
|
| 114 |
+
Args:
|
| 115 |
+
img (Union[Path, str]): The image to load.
|
| 116 |
+
|
| 117 |
+
Returns:
|
| 118 |
+
Image: The loaded PIL image.
|
| 119 |
+
"""
|
| 120 |
+
try:
|
| 121 |
+
if isinstance(img, Path):
|
| 122 |
+
return Image.open(img).convert("RGB")
|
| 123 |
+
elif isinstance(img, str):
|
| 124 |
+
return Image.open(BytesIO(base64.b64decode(img))).convert("RGB")
|
| 125 |
+
except Exception as e:
|
| 126 |
+
raise ValueError(f"Failed to load image: {e}")
|
| 127 |
+
|
| 128 |
+
def _prepare_similarity_map_tensor(
|
| 129 |
+
self, query_embs: torch.Tensor, vespa_sim_maps: List[Dict]
|
| 130 |
+
) -> torch.Tensor:
|
| 131 |
+
"""
|
| 132 |
+
Prepares a similarity map tensor from Vespa similarity maps.
|
| 133 |
+
|
| 134 |
+
Args:
|
| 135 |
+
query_embs (torch.Tensor): Query embeddings tensor.
|
| 136 |
+
vespa_sim_maps (List[Dict]): List of Vespa similarity maps.
|
| 137 |
+
|
| 138 |
+
Returns:
|
| 139 |
+
torch.Tensor: The prepared similarity map tensor.
|
| 140 |
+
"""
|
| 141 |
+
vespa_sim_map_tensor = torch.zeros(
|
| 142 |
+
(len(vespa_sim_maps), query_embs.size(1), self.n_patch, self.n_patch)
|
| 143 |
+
)
|
| 144 |
+
for idx, vespa_sim_map in enumerate(vespa_sim_maps):
|
| 145 |
+
for cell in vespa_sim_map["quantized"]["cells"]:
|
| 146 |
+
patch = int(cell["address"]["patch"])
|
| 147 |
+
query_token = int(cell["address"]["querytoken"])
|
| 148 |
+
value = cell["value"]
|
| 149 |
+
if hasattr(self.processor, "image_seq_length"):
|
| 150 |
+
image_seq_length = self.processor.image_seq_length
|
| 151 |
+
else:
|
| 152 |
+
image_seq_length = 1024
|
| 153 |
+
|
| 154 |
+
if patch >= image_seq_length:
|
| 155 |
+
continue
|
| 156 |
+
vespa_sim_map_tensor[
|
| 157 |
+
idx,
|
| 158 |
+
query_token,
|
| 159 |
+
patch // self.n_patch,
|
| 160 |
+
patch % self.n_patch,
|
| 161 |
+
] = value
|
| 162 |
+
return vespa_sim_map_tensor
|
| 163 |
+
|
| 164 |
+
def _blend_image(
|
| 165 |
+
self, img: Image, sim_map: torch.Tensor, original_size: Tuple[int, int]
|
| 166 |
+
) -> str:
|
| 167 |
+
"""
|
| 168 |
+
Blends an image with a similarity map and encodes it to base64.
|
| 169 |
+
|
| 170 |
+
Args:
|
| 171 |
+
img (Image): The original image.
|
| 172 |
+
sim_map (torch.Tensor): The similarity map tensor.
|
| 173 |
+
original_size (Tuple[int, int]): The original size of the image.
|
| 174 |
+
|
| 175 |
+
Returns:
|
| 176 |
+
str: The base64-encoded blended image.
|
| 177 |
+
"""
|
| 178 |
+
SCALING_FACTOR = 8
|
| 179 |
+
sim_map_resolution = (
|
| 180 |
+
max(32, int(original_size[0] / SCALING_FACTOR)),
|
| 181 |
+
max(32, int(original_size[1] / SCALING_FACTOR)),
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
sim_map_np = sim_map.cpu().float().numpy()
|
| 185 |
+
sim_map_img = Image.fromarray(sim_map_np).resize(
|
| 186 |
+
sim_map_resolution, resample=Image.BICUBIC
|
| 187 |
+
)
|
| 188 |
+
sim_map_resized_np = np.array(sim_map_img, dtype=np.float32)
|
| 189 |
+
sim_map_normalized = self._normalize_sim_map(sim_map_resized_np)
|
| 190 |
+
|
| 191 |
+
heatmap = self.colormap(sim_map_normalized)
|
| 192 |
+
heatmap_img = Image.fromarray((heatmap * 255).astype(np.uint8)).convert("RGBA")
|
| 193 |
+
|
| 194 |
+
buffer = io.BytesIO()
|
| 195 |
+
heatmap_img.save(buffer, format="PNG")
|
| 196 |
+
return base64.b64encode(buffer.getvalue()).decode("utf-8")
|
| 197 |
+
|
| 198 |
+
@staticmethod
|
| 199 |
+
def _normalize_sim_map(sim_map: np.ndarray) -> np.ndarray:
|
| 200 |
+
"""
|
| 201 |
+
Normalizes a similarity map to range [0, 1].
|
| 202 |
+
|
| 203 |
+
Args:
|
| 204 |
+
sim_map (np.ndarray): The similarity map.
|
| 205 |
+
|
| 206 |
+
Returns:
|
| 207 |
+
np.ndarray: The normalized similarity map.
|
| 208 |
+
"""
|
| 209 |
+
sim_map_min, sim_map_max = sim_map.min(), sim_map.max()
|
| 210 |
+
if sim_map_max - sim_map_min > 1e-6:
|
| 211 |
+
return (sim_map - sim_map_min) / (sim_map_max - sim_map_min)
|
| 212 |
+
return np.zeros_like(sim_map)
|
| 213 |
+
|
| 214 |
+
@staticmethod
|
| 215 |
+
def should_filter_token(token: str) -> bool:
|
| 216 |
+
"""
|
| 217 |
+
Determines if a token should be filtered out based on predefined patterns.
|
| 218 |
+
|
| 219 |
+
The function filters out tokens that:
|
| 220 |
+
|
| 221 |
+
- Start with '<' (e.g., '<bos>')
|
| 222 |
+
- Consist entirely of whitespace
|
| 223 |
+
- Are purely punctuation (excluding tokens that contain digits or start with '▁')
|
| 224 |
+
- Start with an underscore '_'
|
| 225 |
+
- Exactly match the word 'Question'
|
| 226 |
+
- Are exactly the single character '▁'
|
| 227 |
+
|
| 228 |
+
Output of test:
|
| 229 |
+
Token: '2' | False
|
| 230 |
+
Token: '0' | False
|
| 231 |
+
Token: '2' | False
|
| 232 |
+
Token: '3' | False
|
| 233 |
+
Token: '▁2' | False
|
| 234 |
+
Token: '▁hi' | False
|
| 235 |
+
Token: 'norwegian' | False
|
| 236 |
+
Token: 'unlisted' | False
|
| 237 |
+
Token: '<bos>' | True
|
| 238 |
+
Token: 'Question' | True
|
| 239 |
+
Token: ':' | True
|
| 240 |
+
Token: '<pad>' | True
|
| 241 |
+
Token: '\n' | True
|
| 242 |
+
Token: '▁' | True
|
| 243 |
+
Token: '?' | True
|
| 244 |
+
Token: ')' | True
|
| 245 |
+
Token: '%' | True
|
| 246 |
+
Token: '/)' | True
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
Args:
|
| 250 |
+
token (str): The token to check.
|
| 251 |
+
|
| 252 |
+
Returns:
|
| 253 |
+
bool: True if the token should be filtered out, False otherwise.
|
| 254 |
+
"""
|
| 255 |
+
pattern = re.compile(
|
| 256 |
+
r"^<.*$|^\s+$|^(?!.*\d)(?!▁)[^\w\s]+$|^_.*$|^Question$|^▁$"
|
| 257 |
+
)
|
| 258 |
+
return bool(pattern.match(token))
|
| 259 |
+
|
| 260 |
+
@lru_cache(maxsize=128)
|
| 261 |
+
def get_query_embeddings_and_token_map(
|
| 262 |
+
self, query: str
|
| 263 |
+
) -> Tuple[torch.Tensor, dict]:
|
| 264 |
+
"""
|
| 265 |
+
Retrieves query embeddings and a token index map.
|
| 266 |
+
|
| 267 |
+
Args:
|
| 268 |
+
query (str): The query string.
|
| 269 |
+
|
| 270 |
+
Returns:
|
| 271 |
+
Tuple[torch.Tensor, dict]: Query embeddings and token index map.
|
| 272 |
+
"""
|
| 273 |
+
inputs = self.processor.process_queries([query]).to(self.model.device)
|
| 274 |
+
with torch.no_grad():
|
| 275 |
+
q_emb = self.model(**inputs).to("cpu")[0]
|
| 276 |
+
|
| 277 |
+
query_tokens = self.processor.tokenizer.tokenize(
|
| 278 |
+
self.processor.decode(inputs.input_ids[0])
|
| 279 |
+
)
|
| 280 |
+
idx_to_token = {idx: token for idx, token in enumerate(query_tokens)}
|
| 281 |
+
return q_emb, idx_to_token
|
src/backend/stopwords.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import spacy
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
# Download the model if it is not already present
|
| 5 |
+
if not spacy.util.is_package("en_core_web_sm"):
|
| 6 |
+
spacy.cli.download("en_core_web_sm")
|
| 7 |
+
nlp = spacy.load("en_core_web_sm")
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
# It would be possible to remove bolding for stopwords without removing them from the query,
|
| 11 |
+
# but that would require a java plugin which we didn't want to complicate this sample app with.
|
| 12 |
+
def filter(text):
|
| 13 |
+
doc = nlp(text)
|
| 14 |
+
tokens = [token.text for token in doc if not token.is_stop]
|
| 15 |
+
if len(tokens) == 0:
|
| 16 |
+
# if we remove all the words we don't have a query at all, so use the original
|
| 17 |
+
return text
|
| 18 |
+
return " ".join(tokens)
|
src/backend/testquery.py
ADDED
|
@@ -0,0 +1,3013 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
token_to_idx = {
|
| 4 |
+
"<bos>": 0,
|
| 5 |
+
"Question": 1,
|
| 6 |
+
":": 2,
|
| 7 |
+
"▁Percentage": 3,
|
| 8 |
+
"▁of": 4,
|
| 9 |
+
"▁non": 5,
|
| 10 |
+
"-": 6,
|
| 11 |
+
"fresh": 7,
|
| 12 |
+
"▁water": 8,
|
| 13 |
+
"▁as": 9,
|
| 14 |
+
"▁source": 10,
|
| 15 |
+
"?": 11,
|
| 16 |
+
"<pad>": 21,
|
| 17 |
+
"\n": 22,
|
| 18 |
+
}
|
| 19 |
+
idx_to_token = {v: k for k, v in token_to_idx.items()}
|
| 20 |
+
q_embs = torch.tensor(
|
| 21 |
+
[
|
| 22 |
+
[
|
| 23 |
+
1.6547e-01,
|
| 24 |
+
-1.8838e-02,
|
| 25 |
+
1.0150e-01,
|
| 26 |
+
-2.2643e-02,
|
| 27 |
+
5.0652e-02,
|
| 28 |
+
3.2039e-02,
|
| 29 |
+
6.8322e-02,
|
| 30 |
+
2.7134e-02,
|
| 31 |
+
7.2197e-03,
|
| 32 |
+
-4.2341e-02,
|
| 33 |
+
-5.8006e-02,
|
| 34 |
+
-1.1389e-01,
|
| 35 |
+
7.0041e-02,
|
| 36 |
+
-6.8021e-02,
|
| 37 |
+
2.4681e-02,
|
| 38 |
+
5.3306e-02,
|
| 39 |
+
4.1714e-02,
|
| 40 |
+
6.2021e-02,
|
| 41 |
+
1.3488e-01,
|
| 42 |
+
3.4943e-02,
|
| 43 |
+
3.8032e-02,
|
| 44 |
+
-3.2724e-02,
|
| 45 |
+
-1.2960e-01,
|
| 46 |
+
1.1453e-02,
|
| 47 |
+
-2.6477e-02,
|
| 48 |
+
3.5219e-02,
|
| 49 |
+
-7.6606e-02,
|
| 50 |
+
2.2387e-01,
|
| 51 |
+
-3.4888e-02,
|
| 52 |
+
-4.0333e-02,
|
| 53 |
+
1.4128e-01,
|
| 54 |
+
4.2248e-02,
|
| 55 |
+
-1.2664e-01,
|
| 56 |
+
-7.8376e-02,
|
| 57 |
+
-2.0356e-02,
|
| 58 |
+
4.2198e-02,
|
| 59 |
+
-7.0776e-02,
|
| 60 |
+
1.3965e-02,
|
| 61 |
+
4.2442e-03,
|
| 62 |
+
7.1987e-02,
|
| 63 |
+
8.5172e-04,
|
| 64 |
+
-6.4878e-02,
|
| 65 |
+
-1.8954e-01,
|
| 66 |
+
-8.6171e-02,
|
| 67 |
+
9.1983e-02,
|
| 68 |
+
-9.3358e-02,
|
| 69 |
+
2.2704e-01,
|
| 70 |
+
1.3102e-02,
|
| 71 |
+
6.5327e-02,
|
| 72 |
+
2.4815e-02,
|
| 73 |
+
-1.4533e-01,
|
| 74 |
+
5.8823e-02,
|
| 75 |
+
-6.1434e-02,
|
| 76 |
+
5.2004e-02,
|
| 77 |
+
-8.4065e-02,
|
| 78 |
+
1.6298e-01,
|
| 79 |
+
8.1965e-02,
|
| 80 |
+
2.6553e-02,
|
| 81 |
+
-1.2377e-01,
|
| 82 |
+
-5.3495e-02,
|
| 83 |
+
-3.4537e-02,
|
| 84 |
+
5.1438e-02,
|
| 85 |
+
8.2665e-03,
|
| 86 |
+
7.9407e-02,
|
| 87 |
+
5.8799e-02,
|
| 88 |
+
-3.5538e-02,
|
| 89 |
+
1.9870e-01,
|
| 90 |
+
6.2459e-02,
|
| 91 |
+
1.6154e-01,
|
| 92 |
+
7.2921e-02,
|
| 93 |
+
-9.7275e-02,
|
| 94 |
+
3.0933e-02,
|
| 95 |
+
-1.0579e-02,
|
| 96 |
+
-1.4484e-01,
|
| 97 |
+
-4.8761e-02,
|
| 98 |
+
-5.3119e-02,
|
| 99 |
+
6.2644e-02,
|
| 100 |
+
2.2985e-02,
|
| 101 |
+
-2.1209e-01,
|
| 102 |
+
9.0963e-02,
|
| 103 |
+
-2.6955e-02,
|
| 104 |
+
-7.7520e-02,
|
| 105 |
+
1.2072e-01,
|
| 106 |
+
-1.9626e-02,
|
| 107 |
+
5.8813e-02,
|
| 108 |
+
-1.2730e-01,
|
| 109 |
+
1.5610e-01,
|
| 110 |
+
-1.6914e-01,
|
| 111 |
+
6.5033e-02,
|
| 112 |
+
8.5765e-02,
|
| 113 |
+
1.2701e-01,
|
| 114 |
+
6.5633e-02,
|
| 115 |
+
-1.0309e-01,
|
| 116 |
+
-8.0259e-02,
|
| 117 |
+
4.5913e-02,
|
| 118 |
+
-3.3277e-02,
|
| 119 |
+
1.9227e-01,
|
| 120 |
+
-2.3351e-02,
|
| 121 |
+
-8.0545e-02,
|
| 122 |
+
-9.8760e-03,
|
| 123 |
+
-4.1836e-02,
|
| 124 |
+
1.2041e-01,
|
| 125 |
+
8.1419e-02,
|
| 126 |
+
1.4848e-01,
|
| 127 |
+
7.2537e-02,
|
| 128 |
+
-4.7115e-03,
|
| 129 |
+
4.1489e-02,
|
| 130 |
+
4.3031e-02,
|
| 131 |
+
-1.3515e-01,
|
| 132 |
+
1.0383e-01,
|
| 133 |
+
-9.4411e-02,
|
| 134 |
+
2.8965e-02,
|
| 135 |
+
1.9185e-01,
|
| 136 |
+
-1.4600e-02,
|
| 137 |
+
-8.0910e-02,
|
| 138 |
+
-2.9022e-02,
|
| 139 |
+
-4.4347e-02,
|
| 140 |
+
-8.8980e-03,
|
| 141 |
+
2.8737e-03,
|
| 142 |
+
4.2124e-02,
|
| 143 |
+
-1.6609e-02,
|
| 144 |
+
4.2994e-02,
|
| 145 |
+
-7.2814e-02,
|
| 146 |
+
-2.9573e-02,
|
| 147 |
+
-1.2666e-01,
|
| 148 |
+
-4.3703e-02,
|
| 149 |
+
-7.2094e-02,
|
| 150 |
+
-2.7486e-02,
|
| 151 |
+
],
|
| 152 |
+
[
|
| 153 |
+
-9.8454e-02,
|
| 154 |
+
-1.2954e-01,
|
| 155 |
+
6.5702e-02,
|
| 156 |
+
-9.0006e-03,
|
| 157 |
+
-1.0934e-01,
|
| 158 |
+
3.2155e-02,
|
| 159 |
+
-1.1444e-01,
|
| 160 |
+
-1.0309e-01,
|
| 161 |
+
5.7024e-02,
|
| 162 |
+
1.0124e-01,
|
| 163 |
+
2.0721e-02,
|
| 164 |
+
-5.2608e-03,
|
| 165 |
+
6.9916e-02,
|
| 166 |
+
1.8036e-02,
|
| 167 |
+
3.1653e-02,
|
| 168 |
+
2.1923e-02,
|
| 169 |
+
-9.2523e-02,
|
| 170 |
+
-1.8215e-02,
|
| 171 |
+
1.2974e-01,
|
| 172 |
+
-2.9632e-02,
|
| 173 |
+
-1.3854e-01,
|
| 174 |
+
2.5710e-02,
|
| 175 |
+
-1.1727e-03,
|
| 176 |
+
1.0245e-01,
|
| 177 |
+
-2.0731e-01,
|
| 178 |
+
4.3669e-02,
|
| 179 |
+
-7.0196e-02,
|
| 180 |
+
-1.6697e-01,
|
| 181 |
+
6.6050e-02,
|
| 182 |
+
9.9776e-02,
|
| 183 |
+
-1.2227e-01,
|
| 184 |
+
9.4000e-02,
|
| 185 |
+
1.1945e-01,
|
| 186 |
+
2.4611e-02,
|
| 187 |
+
-1.4073e-01,
|
| 188 |
+
9.3476e-02,
|
| 189 |
+
2.1170e-01,
|
| 190 |
+
-7.4522e-02,
|
| 191 |
+
-5.3362e-02,
|
| 192 |
+
-4.1198e-03,
|
| 193 |
+
8.3880e-02,
|
| 194 |
+
2.6590e-02,
|
| 195 |
+
-4.8489e-02,
|
| 196 |
+
-3.1279e-02,
|
| 197 |
+
-9.3401e-03,
|
| 198 |
+
-1.5945e-01,
|
| 199 |
+
-6.6368e-02,
|
| 200 |
+
7.5715e-02,
|
| 201 |
+
5.6884e-02,
|
| 202 |
+
1.2861e-01,
|
| 203 |
+
1.0073e-02,
|
| 204 |
+
-1.7185e-02,
|
| 205 |
+
1.1545e-01,
|
| 206 |
+
2.8725e-02,
|
| 207 |
+
-9.4969e-02,
|
| 208 |
+
-4.5517e-02,
|
| 209 |
+
3.1253e-02,
|
| 210 |
+
2.1135e-02,
|
| 211 |
+
-1.4505e-02,
|
| 212 |
+
9.0893e-02,
|
| 213 |
+
-6.2680e-02,
|
| 214 |
+
-7.2855e-02,
|
| 215 |
+
-1.1275e-01,
|
| 216 |
+
-1.8433e-01,
|
| 217 |
+
1.4693e-01,
|
| 218 |
+
4.0366e-02,
|
| 219 |
+
6.6879e-02,
|
| 220 |
+
-8.5653e-03,
|
| 221 |
+
1.0663e-01,
|
| 222 |
+
-1.2342e-01,
|
| 223 |
+
2.5350e-01,
|
| 224 |
+
-3.2227e-02,
|
| 225 |
+
9.9404e-02,
|
| 226 |
+
3.7340e-02,
|
| 227 |
+
4.5462e-04,
|
| 228 |
+
-2.3015e-01,
|
| 229 |
+
4.9006e-02,
|
| 230 |
+
1.0079e-01,
|
| 231 |
+
-4.7179e-02,
|
| 232 |
+
6.7642e-02,
|
| 233 |
+
-1.0833e-01,
|
| 234 |
+
1.0030e-01,
|
| 235 |
+
1.2838e-01,
|
| 236 |
+
-9.2911e-03,
|
| 237 |
+
1.2342e-01,
|
| 238 |
+
-4.8455e-02,
|
| 239 |
+
5.3904e-03,
|
| 240 |
+
4.5178e-02,
|
| 241 |
+
3.8961e-02,
|
| 242 |
+
1.3383e-01,
|
| 243 |
+
-1.2236e-02,
|
| 244 |
+
8.2026e-03,
|
| 245 |
+
4.3735e-03,
|
| 246 |
+
-7.1725e-02,
|
| 247 |
+
6.4360e-02,
|
| 248 |
+
1.0004e-01,
|
| 249 |
+
6.6840e-02,
|
| 250 |
+
6.5649e-02,
|
| 251 |
+
-1.3978e-02,
|
| 252 |
+
1.2810e-01,
|
| 253 |
+
4.4325e-03,
|
| 254 |
+
1.1136e-01,
|
| 255 |
+
-1.7329e-01,
|
| 256 |
+
-3.4472e-02,
|
| 257 |
+
-1.4066e-01,
|
| 258 |
+
1.5641e-02,
|
| 259 |
+
-3.3600e-02,
|
| 260 |
+
-7.6192e-02,
|
| 261 |
+
5.3085e-02,
|
| 262 |
+
-7.2859e-03,
|
| 263 |
+
2.8798e-02,
|
| 264 |
+
-3.3748e-02,
|
| 265 |
+
-7.7591e-02,
|
| 266 |
+
-4.0927e-02,
|
| 267 |
+
-3.6577e-02,
|
| 268 |
+
1.4012e-02,
|
| 269 |
+
-8.1780e-02,
|
| 270 |
+
-4.6315e-03,
|
| 271 |
+
-1.6508e-02,
|
| 272 |
+
-2.4506e-02,
|
| 273 |
+
1.5122e-01,
|
| 274 |
+
7.8270e-02,
|
| 275 |
+
8.6502e-02,
|
| 276 |
+
-2.4651e-02,
|
| 277 |
+
-1.0286e-01,
|
| 278 |
+
-1.2171e-02,
|
| 279 |
+
-7.9000e-02,
|
| 280 |
+
1.1161e-01,
|
| 281 |
+
],
|
| 282 |
+
[
|
| 283 |
+
6.4320e-02,
|
| 284 |
+
-2.6815e-02,
|
| 285 |
+
1.2390e-01,
|
| 286 |
+
8.6642e-02,
|
| 287 |
+
5.3320e-02,
|
| 288 |
+
9.1074e-02,
|
| 289 |
+
-8.9753e-02,
|
| 290 |
+
1.6141e-02,
|
| 291 |
+
-5.0281e-02,
|
| 292 |
+
1.0177e-01,
|
| 293 |
+
4.5343e-02,
|
| 294 |
+
9.1281e-02,
|
| 295 |
+
-8.2592e-03,
|
| 296 |
+
-1.4100e-02,
|
| 297 |
+
-4.7048e-02,
|
| 298 |
+
-8.6034e-02,
|
| 299 |
+
-1.1608e-01,
|
| 300 |
+
-8.4754e-02,
|
| 301 |
+
1.0302e-01,
|
| 302 |
+
-1.2210e-02,
|
| 303 |
+
8.5147e-02,
|
| 304 |
+
1.3103e-01,
|
| 305 |
+
-3.3592e-03,
|
| 306 |
+
-1.4328e-02,
|
| 307 |
+
-4.6128e-03,
|
| 308 |
+
2.1401e-02,
|
| 309 |
+
-1.7464e-01,
|
| 310 |
+
-3.9111e-02,
|
| 311 |
+
2.0886e-02,
|
| 312 |
+
8.9284e-02,
|
| 313 |
+
1.3262e-01,
|
| 314 |
+
7.0918e-02,
|
| 315 |
+
-1.3693e-02,
|
| 316 |
+
-9.7673e-02,
|
| 317 |
+
-5.3411e-02,
|
| 318 |
+
-6.7563e-02,
|
| 319 |
+
2.3017e-02,
|
| 320 |
+
-3.4614e-02,
|
| 321 |
+
3.6464e-02,
|
| 322 |
+
-4.6408e-02,
|
| 323 |
+
1.4866e-01,
|
| 324 |
+
-2.1191e-01,
|
| 325 |
+
-6.4368e-02,
|
| 326 |
+
-3.0555e-02,
|
| 327 |
+
7.2177e-02,
|
| 328 |
+
2.4685e-02,
|
| 329 |
+
8.6115e-02,
|
| 330 |
+
-5.8688e-02,
|
| 331 |
+
-2.8230e-03,
|
| 332 |
+
1.1166e-01,
|
| 333 |
+
1.8380e-01,
|
| 334 |
+
3.6462e-02,
|
| 335 |
+
-1.4943e-02,
|
| 336 |
+
-1.4276e-01,
|
| 337 |
+
1.0795e-01,
|
| 338 |
+
1.9204e-02,
|
| 339 |
+
-6.5320e-02,
|
| 340 |
+
1.0561e-01,
|
| 341 |
+
-1.3642e-01,
|
| 342 |
+
-4.3444e-02,
|
| 343 |
+
-6.4725e-02,
|
| 344 |
+
-1.3094e-01,
|
| 345 |
+
1.9447e-02,
|
| 346 |
+
-1.3199e-01,
|
| 347 |
+
8.7880e-02,
|
| 348 |
+
5.8078e-02,
|
| 349 |
+
-2.5612e-02,
|
| 350 |
+
7.7620e-02,
|
| 351 |
+
-2.5044e-02,
|
| 352 |
+
1.0772e-02,
|
| 353 |
+
6.5417e-02,
|
| 354 |
+
8.2137e-02,
|
| 355 |
+
-2.8482e-02,
|
| 356 |
+
5.5003e-02,
|
| 357 |
+
-1.1163e-01,
|
| 358 |
+
1.7200e-03,
|
| 359 |
+
-1.0106e-01,
|
| 360 |
+
-1.8413e-02,
|
| 361 |
+
1.2838e-01,
|
| 362 |
+
-1.2991e-01,
|
| 363 |
+
-1.8546e-02,
|
| 364 |
+
1.0517e-01,
|
| 365 |
+
1.0279e-01,
|
| 366 |
+
-8.1887e-02,
|
| 367 |
+
1.0885e-01,
|
| 368 |
+
-1.0635e-01,
|
| 369 |
+
1.2035e-01,
|
| 370 |
+
1.1769e-01,
|
| 371 |
+
-2.8768e-02,
|
| 372 |
+
-3.3413e-02,
|
| 373 |
+
1.3779e-01,
|
| 374 |
+
1.4403e-02,
|
| 375 |
+
2.3429e-02,
|
| 376 |
+
-1.2761e-01,
|
| 377 |
+
7.2160e-02,
|
| 378 |
+
-1.0512e-01,
|
| 379 |
+
-1.7202e-02,
|
| 380 |
+
5.3549e-02,
|
| 381 |
+
5.5205e-02,
|
| 382 |
+
9.2863e-02,
|
| 383 |
+
-2.3728e-02,
|
| 384 |
+
-5.1368e-02,
|
| 385 |
+
-3.7719e-02,
|
| 386 |
+
-4.7308e-02,
|
| 387 |
+
-2.2489e-02,
|
| 388 |
+
4.5195e-02,
|
| 389 |
+
1.0398e-01,
|
| 390 |
+
-2.2197e-02,
|
| 391 |
+
-1.7208e-01,
|
| 392 |
+
7.4649e-02,
|
| 393 |
+
-7.7925e-02,
|
| 394 |
+
-6.4237e-02,
|
| 395 |
+
2.8195e-02,
|
| 396 |
+
2.2692e-01,
|
| 397 |
+
-9.7749e-02,
|
| 398 |
+
2.4283e-01,
|
| 399 |
+
-4.0124e-02,
|
| 400 |
+
1.8797e-02,
|
| 401 |
+
-6.1516e-02,
|
| 402 |
+
6.5331e-03,
|
| 403 |
+
1.3717e-01,
|
| 404 |
+
9.9761e-02,
|
| 405 |
+
5.4705e-02,
|
| 406 |
+
3.5325e-02,
|
| 407 |
+
1.9071e-01,
|
| 408 |
+
-6.1137e-02,
|
| 409 |
+
1.6656e-01,
|
| 410 |
+
3.4067e-02,
|
| 411 |
+
],
|
| 412 |
+
[
|
| 413 |
+
1.0896e-01,
|
| 414 |
+
-9.4366e-03,
|
| 415 |
+
1.2956e-01,
|
| 416 |
+
7.8127e-02,
|
| 417 |
+
5.5422e-02,
|
| 418 |
+
3.9155e-02,
|
| 419 |
+
-5.8379e-03,
|
| 420 |
+
-4.4257e-02,
|
| 421 |
+
-7.5182e-02,
|
| 422 |
+
1.0452e-01,
|
| 423 |
+
4.4595e-02,
|
| 424 |
+
2.0972e-02,
|
| 425 |
+
1.1071e-01,
|
| 426 |
+
7.4710e-02,
|
| 427 |
+
-7.5500e-02,
|
| 428 |
+
-5.3393e-02,
|
| 429 |
+
-1.5478e-02,
|
| 430 |
+
-5.4455e-03,
|
| 431 |
+
5.6779e-02,
|
| 432 |
+
-6.3919e-02,
|
| 433 |
+
5.1792e-02,
|
| 434 |
+
1.2070e-01,
|
| 435 |
+
-5.3707e-02,
|
| 436 |
+
4.5715e-02,
|
| 437 |
+
-9.3062e-02,
|
| 438 |
+
3.0224e-02,
|
| 439 |
+
-1.5892e-01,
|
| 440 |
+
-2.1702e-02,
|
| 441 |
+
1.7942e-03,
|
| 442 |
+
1.4574e-01,
|
| 443 |
+
2.0721e-01,
|
| 444 |
+
-2.8224e-02,
|
| 445 |
+
-5.8104e-02,
|
| 446 |
+
-1.1645e-01,
|
| 447 |
+
-1.1515e-01,
|
| 448 |
+
-1.5202e-01,
|
| 449 |
+
-3.9751e-02,
|
| 450 |
+
6.0342e-02,
|
| 451 |
+
7.8182e-02,
|
| 452 |
+
-2.1132e-02,
|
| 453 |
+
9.6468e-02,
|
| 454 |
+
-5.3148e-02,
|
| 455 |
+
-3.0343e-02,
|
| 456 |
+
7.9363e-02,
|
| 457 |
+
1.0752e-01,
|
| 458 |
+
3.1086e-02,
|
| 459 |
+
1.9322e-02,
|
| 460 |
+
-1.1134e-01,
|
| 461 |
+
1.6342e-02,
|
| 462 |
+
3.0358e-02,
|
| 463 |
+
1.8543e-01,
|
| 464 |
+
5.5353e-02,
|
| 465 |
+
-8.6656e-02,
|
| 466 |
+
-1.5650e-01,
|
| 467 |
+
1.2087e-01,
|
| 468 |
+
-3.7852e-02,
|
| 469 |
+
-6.9116e-02,
|
| 470 |
+
5.9981e-03,
|
| 471 |
+
1.9205e-02,
|
| 472 |
+
-1.0314e-01,
|
| 473 |
+
-6.8082e-02,
|
| 474 |
+
-1.3078e-01,
|
| 475 |
+
3.8448e-02,
|
| 476 |
+
-9.2233e-02,
|
| 477 |
+
1.0965e-01,
|
| 478 |
+
6.6332e-02,
|
| 479 |
+
-2.5805e-02,
|
| 480 |
+
1.2299e-01,
|
| 481 |
+
2.8629e-02,
|
| 482 |
+
-4.4949e-02,
|
| 483 |
+
4.5560e-02,
|
| 484 |
+
1.0507e-01,
|
| 485 |
+
-1.0271e-01,
|
| 486 |
+
1.6237e-02,
|
| 487 |
+
-1.4555e-01,
|
| 488 |
+
-4.5335e-02,
|
| 489 |
+
-1.3477e-01,
|
| 490 |
+
1.0230e-02,
|
| 491 |
+
1.2380e-01,
|
| 492 |
+
-1.0681e-01,
|
| 493 |
+
1.4412e-02,
|
| 494 |
+
1.2396e-01,
|
| 495 |
+
8.5290e-02,
|
| 496 |
+
-2.5138e-02,
|
| 497 |
+
1.0191e-01,
|
| 498 |
+
-1.3413e-01,
|
| 499 |
+
8.5871e-02,
|
| 500 |
+
1.3389e-01,
|
| 501 |
+
-3.6357e-02,
|
| 502 |
+
-3.9740e-02,
|
| 503 |
+
2.1128e-01,
|
| 504 |
+
1.0263e-02,
|
| 505 |
+
2.5547e-02,
|
| 506 |
+
-7.0139e-02,
|
| 507 |
+
1.0178e-01,
|
| 508 |
+
-1.2729e-01,
|
| 509 |
+
-1.0717e-01,
|
| 510 |
+
-4.9394e-02,
|
| 511 |
+
7.7645e-02,
|
| 512 |
+
7.4589e-02,
|
| 513 |
+
-8.2835e-02,
|
| 514 |
+
-4.2227e-02,
|
| 515 |
+
-3.6417e-02,
|
| 516 |
+
-2.2900e-02,
|
| 517 |
+
-2.1010e-02,
|
| 518 |
+
2.7898e-02,
|
| 519 |
+
2.7314e-02,
|
| 520 |
+
2.2172e-02,
|
| 521 |
+
-7.1122e-02,
|
| 522 |
+
5.1570e-02,
|
| 523 |
+
2.1860e-02,
|
| 524 |
+
-3.5103e-03,
|
| 525 |
+
-5.4524e-02,
|
| 526 |
+
1.7485e-01,
|
| 527 |
+
-8.3810e-02,
|
| 528 |
+
2.3868e-01,
|
| 529 |
+
5.9468e-02,
|
| 530 |
+
-2.6706e-02,
|
| 531 |
+
-2.6617e-02,
|
| 532 |
+
3.3851e-02,
|
| 533 |
+
6.3651e-02,
|
| 534 |
+
1.0611e-01,
|
| 535 |
+
9.6252e-02,
|
| 536 |
+
-6.8701e-02,
|
| 537 |
+
1.8108e-01,
|
| 538 |
+
-1.0178e-01,
|
| 539 |
+
1.6935e-01,
|
| 540 |
+
5.9301e-02,
|
| 541 |
+
],
|
| 542 |
+
[
|
| 543 |
+
1.3364e-01,
|
| 544 |
+
6.6797e-02,
|
| 545 |
+
1.0182e-01,
|
| 546 |
+
6.1569e-02,
|
| 547 |
+
-1.4169e-04,
|
| 548 |
+
1.1567e-01,
|
| 549 |
+
-3.1255e-03,
|
| 550 |
+
-8.9336e-02,
|
| 551 |
+
5.3206e-03,
|
| 552 |
+
1.7179e-01,
|
| 553 |
+
1.3974e-01,
|
| 554 |
+
-6.5797e-02,
|
| 555 |
+
1.2566e-01,
|
| 556 |
+
6.1290e-02,
|
| 557 |
+
-1.3671e-01,
|
| 558 |
+
-1.1113e-01,
|
| 559 |
+
1.6596e-01,
|
| 560 |
+
6.2694e-02,
|
| 561 |
+
-1.6573e-02,
|
| 562 |
+
-1.8648e-02,
|
| 563 |
+
2.1086e-02,
|
| 564 |
+
9.6320e-03,
|
| 565 |
+
-1.0017e-01,
|
| 566 |
+
2.3561e-02,
|
| 567 |
+
-6.2797e-02,
|
| 568 |
+
2.1202e-02,
|
| 569 |
+
-1.3333e-01,
|
| 570 |
+
1.4728e-01,
|
| 571 |
+
1.9824e-03,
|
| 572 |
+
1.6832e-01,
|
| 573 |
+
1.7138e-01,
|
| 574 |
+
4.6578e-02,
|
| 575 |
+
-1.2989e-01,
|
| 576 |
+
3.2167e-02,
|
| 577 |
+
-7.7753e-02,
|
| 578 |
+
-1.1548e-01,
|
| 579 |
+
4.3367e-02,
|
| 580 |
+
-4.5640e-02,
|
| 581 |
+
4.3583e-02,
|
| 582 |
+
-8.9393e-03,
|
| 583 |
+
5.3231e-02,
|
| 584 |
+
-4.8284e-02,
|
| 585 |
+
3.1841e-04,
|
| 586 |
+
6.6374e-02,
|
| 587 |
+
7.7363e-02,
|
| 588 |
+
4.0000e-02,
|
| 589 |
+
1.5414e-02,
|
| 590 |
+
-9.6156e-02,
|
| 591 |
+
1.1389e-01,
|
| 592 |
+
7.1118e-02,
|
| 593 |
+
3.0042e-02,
|
| 594 |
+
5.9752e-02,
|
| 595 |
+
-6.4565e-02,
|
| 596 |
+
-1.2914e-01,
|
| 597 |
+
1.1048e-01,
|
| 598 |
+
1.2409e-02,
|
| 599 |
+
-9.9385e-02,
|
| 600 |
+
1.8671e-02,
|
| 601 |
+
2.1383e-02,
|
| 602 |
+
3.7012e-03,
|
| 603 |
+
-1.1497e-01,
|
| 604 |
+
-6.8653e-02,
|
| 605 |
+
3.0582e-02,
|
| 606 |
+
-1.1567e-01,
|
| 607 |
+
1.4165e-01,
|
| 608 |
+
3.7493e-02,
|
| 609 |
+
-6.0779e-02,
|
| 610 |
+
1.0989e-01,
|
| 611 |
+
8.6001e-02,
|
| 612 |
+
-5.6139e-02,
|
| 613 |
+
2.0710e-02,
|
| 614 |
+
9.8577e-02,
|
| 615 |
+
-9.9427e-02,
|
| 616 |
+
5.8372e-02,
|
| 617 |
+
-1.3443e-01,
|
| 618 |
+
-1.3021e-02,
|
| 619 |
+
-1.3802e-01,
|
| 620 |
+
7.6053e-02,
|
| 621 |
+
1.2181e-01,
|
| 622 |
+
-8.7719e-02,
|
| 623 |
+
1.0967e-02,
|
| 624 |
+
1.3160e-01,
|
| 625 |
+
4.7032e-02,
|
| 626 |
+
-6.3351e-02,
|
| 627 |
+
7.1883e-02,
|
| 628 |
+
-9.7565e-02,
|
| 629 |
+
1.4424e-01,
|
| 630 |
+
1.2353e-01,
|
| 631 |
+
-6.1527e-02,
|
| 632 |
+
2.4263e-02,
|
| 633 |
+
2.9356e-01,
|
| 634 |
+
6.2813e-02,
|
| 635 |
+
-4.5265e-03,
|
| 636 |
+
-1.0213e-01,
|
| 637 |
+
1.4227e-02,
|
| 638 |
+
-7.9267e-02,
|
| 639 |
+
-1.0845e-01,
|
| 640 |
+
-2.0014e-02,
|
| 641 |
+
2.8542e-02,
|
| 642 |
+
9.7207e-02,
|
| 643 |
+
-2.5234e-02,
|
| 644 |
+
-7.3668e-02,
|
| 645 |
+
-3.0084e-02,
|
| 646 |
+
-1.2958e-02,
|
| 647 |
+
-3.9597e-02,
|
| 648 |
+
-7.2243e-02,
|
| 649 |
+
5.3054e-02,
|
| 650 |
+
3.1470e-03,
|
| 651 |
+
-1.9800e-02,
|
| 652 |
+
1.3476e-01,
|
| 653 |
+
-1.6873e-02,
|
| 654 |
+
5.2286e-02,
|
| 655 |
+
2.0254e-02,
|
| 656 |
+
1.0554e-01,
|
| 657 |
+
-3.0395e-02,
|
| 658 |
+
8.6349e-02,
|
| 659 |
+
7.6580e-02,
|
| 660 |
+
-3.0139e-02,
|
| 661 |
+
-4.8131e-02,
|
| 662 |
+
-4.5770e-02,
|
| 663 |
+
1.5154e-01,
|
| 664 |
+
1.1276e-01,
|
| 665 |
+
5.7244e-02,
|
| 666 |
+
8.0574e-02,
|
| 667 |
+
1.5610e-01,
|
| 668 |
+
-1.5523e-01,
|
| 669 |
+
1.0428e-01,
|
| 670 |
+
5.7947e-02,
|
| 671 |
+
],
|
| 672 |
+
[
|
| 673 |
+
7.0440e-02,
|
| 674 |
+
1.4300e-01,
|
| 675 |
+
6.0559e-02,
|
| 676 |
+
1.9177e-02,
|
| 677 |
+
-9.0313e-02,
|
| 678 |
+
1.7104e-01,
|
| 679 |
+
-5.1137e-02,
|
| 680 |
+
-1.0229e-01,
|
| 681 |
+
-2.8831e-02,
|
| 682 |
+
1.5385e-01,
|
| 683 |
+
-8.4017e-03,
|
| 684 |
+
-4.9185e-03,
|
| 685 |
+
1.0820e-01,
|
| 686 |
+
1.0022e-01,
|
| 687 |
+
-1.9284e-01,
|
| 688 |
+
-2.7293e-02,
|
| 689 |
+
4.9526e-02,
|
| 690 |
+
5.5152e-02,
|
| 691 |
+
-6.7003e-02,
|
| 692 |
+
-7.0313e-03,
|
| 693 |
+
-3.3208e-02,
|
| 694 |
+
1.3815e-02,
|
| 695 |
+
-6.0694e-02,
|
| 696 |
+
6.2041e-02,
|
| 697 |
+
-3.2288e-02,
|
| 698 |
+
1.1629e-01,
|
| 699 |
+
-7.5270e-02,
|
| 700 |
+
2.1824e-01,
|
| 701 |
+
-2.5215e-03,
|
| 702 |
+
1.8179e-01,
|
| 703 |
+
1.5514e-01,
|
| 704 |
+
1.0494e-01,
|
| 705 |
+
-1.2390e-01,
|
| 706 |
+
-1.2241e-03,
|
| 707 |
+
6.1079e-04,
|
| 708 |
+
-5.8730e-02,
|
| 709 |
+
6.1313e-02,
|
| 710 |
+
-7.8853e-02,
|
| 711 |
+
6.0292e-02,
|
| 712 |
+
-9.1497e-04,
|
| 713 |
+
7.9087e-02,
|
| 714 |
+
-1.8246e-02,
|
| 715 |
+
5.0215e-03,
|
| 716 |
+
3.5083e-02,
|
| 717 |
+
5.9616e-02,
|
| 718 |
+
5.9520e-02,
|
| 719 |
+
6.0224e-02,
|
| 720 |
+
-1.3079e-01,
|
| 721 |
+
1.6500e-01,
|
| 722 |
+
4.4308e-03,
|
| 723 |
+
4.2712e-02,
|
| 724 |
+
5.5916e-02,
|
| 725 |
+
-5.4616e-02,
|
| 726 |
+
-8.5617e-02,
|
| 727 |
+
1.1235e-01,
|
| 728 |
+
6.5911e-03,
|
| 729 |
+
-6.1463e-02,
|
| 730 |
+
3.7832e-02,
|
| 731 |
+
3.4189e-02,
|
| 732 |
+
-1.1295e-02,
|
| 733 |
+
-8.0972e-02,
|
| 734 |
+
-1.0051e-02,
|
| 735 |
+
-2.6856e-02,
|
| 736 |
+
-7.9570e-02,
|
| 737 |
+
1.2776e-01,
|
| 738 |
+
6.5826e-02,
|
| 739 |
+
-3.1759e-02,
|
| 740 |
+
9.6016e-02,
|
| 741 |
+
6.7249e-02,
|
| 742 |
+
-4.5115e-02,
|
| 743 |
+
6.3695e-03,
|
| 744 |
+
1.2092e-01,
|
| 745 |
+
-1.3821e-01,
|
| 746 |
+
-9.7066e-02,
|
| 747 |
+
-1.5063e-02,
|
| 748 |
+
2.4618e-02,
|
| 749 |
+
-1.9589e-01,
|
| 750 |
+
5.8625e-02,
|
| 751 |
+
1.7886e-01,
|
| 752 |
+
-6.3740e-02,
|
| 753 |
+
-1.7241e-02,
|
| 754 |
+
7.3394e-02,
|
| 755 |
+
5.8903e-02,
|
| 756 |
+
-1.6557e-02,
|
| 757 |
+
-1.9226e-02,
|
| 758 |
+
-1.0912e-01,
|
| 759 |
+
8.7902e-02,
|
| 760 |
+
6.4426e-02,
|
| 761 |
+
4.8019e-02,
|
| 762 |
+
8.1223e-02,
|
| 763 |
+
2.9888e-01,
|
| 764 |
+
8.7458e-02,
|
| 765 |
+
4.4167e-02,
|
| 766 |
+
-1.3228e-01,
|
| 767 |
+
5.9629e-02,
|
| 768 |
+
-1.0696e-01,
|
| 769 |
+
-1.4102e-01,
|
| 770 |
+
-5.2509e-02,
|
| 771 |
+
-1.9981e-02,
|
| 772 |
+
1.6788e-01,
|
| 773 |
+
9.7499e-02,
|
| 774 |
+
-5.4125e-02,
|
| 775 |
+
-8.2383e-02,
|
| 776 |
+
-6.3908e-02,
|
| 777 |
+
-6.8830e-02,
|
| 778 |
+
-1.2622e-01,
|
| 779 |
+
3.1651e-02,
|
| 780 |
+
4.4592e-02,
|
| 781 |
+
-1.3325e-02,
|
| 782 |
+
1.1260e-01,
|
| 783 |
+
-3.9567e-02,
|
| 784 |
+
6.9631e-03,
|
| 785 |
+
1.4943e-01,
|
| 786 |
+
8.6930e-02,
|
| 787 |
+
-3.6171e-03,
|
| 788 |
+
-5.6886e-02,
|
| 789 |
+
-8.3102e-03,
|
| 790 |
+
-2.6001e-02,
|
| 791 |
+
-1.5187e-02,
|
| 792 |
+
-1.8835e-02,
|
| 793 |
+
2.3583e-02,
|
| 794 |
+
9.5520e-02,
|
| 795 |
+
-3.4944e-02,
|
| 796 |
+
4.5537e-02,
|
| 797 |
+
6.1444e-02,
|
| 798 |
+
-1.7165e-01,
|
| 799 |
+
1.0230e-01,
|
| 800 |
+
2.0319e-02,
|
| 801 |
+
],
|
| 802 |
+
[
|
| 803 |
+
7.7065e-02,
|
| 804 |
+
1.4466e-01,
|
| 805 |
+
1.0796e-01,
|
| 806 |
+
9.7362e-03,
|
| 807 |
+
-9.3062e-02,
|
| 808 |
+
2.0065e-01,
|
| 809 |
+
-9.3982e-03,
|
| 810 |
+
-1.2871e-01,
|
| 811 |
+
-4.6724e-02,
|
| 812 |
+
1.6573e-01,
|
| 813 |
+
-1.7444e-02,
|
| 814 |
+
-3.1211e-02,
|
| 815 |
+
9.7404e-02,
|
| 816 |
+
9.6222e-02,
|
| 817 |
+
-1.4772e-01,
|
| 818 |
+
-5.6838e-02,
|
| 819 |
+
9.6276e-02,
|
| 820 |
+
7.7819e-02,
|
| 821 |
+
-1.1884e-01,
|
| 822 |
+
-4.5898e-02,
|
| 823 |
+
-7.3665e-02,
|
| 824 |
+
2.1005e-02,
|
| 825 |
+
-2.8032e-02,
|
| 826 |
+
7.0900e-02,
|
| 827 |
+
-7.7625e-02,
|
| 828 |
+
7.0269e-02,
|
| 829 |
+
-7.0747e-02,
|
| 830 |
+
2.5605e-01,
|
| 831 |
+
1.9427e-04,
|
| 832 |
+
1.4614e-01,
|
| 833 |
+
1.6723e-01,
|
| 834 |
+
1.0016e-01,
|
| 835 |
+
-7.8961e-02,
|
| 836 |
+
1.3307e-02,
|
| 837 |
+
-1.1207e-02,
|
| 838 |
+
-7.1492e-02,
|
| 839 |
+
7.5561e-02,
|
| 840 |
+
-1.3290e-02,
|
| 841 |
+
4.4527e-02,
|
| 842 |
+
-2.4224e-02,
|
| 843 |
+
8.7846e-02,
|
| 844 |
+
4.7492e-02,
|
| 845 |
+
-7.0398e-02,
|
| 846 |
+
-2.6663e-02,
|
| 847 |
+
4.9730e-02,
|
| 848 |
+
6.6743e-02,
|
| 849 |
+
3.1060e-02,
|
| 850 |
+
-7.8352e-02,
|
| 851 |
+
1.0100e-01,
|
| 852 |
+
6.4963e-02,
|
| 853 |
+
1.6746e-02,
|
| 854 |
+
3.0324e-02,
|
| 855 |
+
-2.6583e-02,
|
| 856 |
+
-7.8028e-02,
|
| 857 |
+
7.0180e-02,
|
| 858 |
+
3.8924e-02,
|
| 859 |
+
-8.5861e-02,
|
| 860 |
+
-3.3792e-02,
|
| 861 |
+
6.1542e-02,
|
| 862 |
+
1.6180e-02,
|
| 863 |
+
-7.7865e-02,
|
| 864 |
+
3.9551e-02,
|
| 865 |
+
2.9772e-02,
|
| 866 |
+
-7.0824e-02,
|
| 867 |
+
1.5235e-01,
|
| 868 |
+
4.8718e-02,
|
| 869 |
+
1.5973e-03,
|
| 870 |
+
8.7719e-02,
|
| 871 |
+
7.7414e-02,
|
| 872 |
+
-6.4385e-02,
|
| 873 |
+
-6.4330e-02,
|
| 874 |
+
1.3965e-01,
|
| 875 |
+
-1.6355e-01,
|
| 876 |
+
-6.5261e-02,
|
| 877 |
+
-6.2693e-02,
|
| 878 |
+
4.9435e-02,
|
| 879 |
+
-1.5245e-01,
|
| 880 |
+
6.6557e-02,
|
| 881 |
+
1.5213e-01,
|
| 882 |
+
-8.2073e-02,
|
| 883 |
+
1.4664e-02,
|
| 884 |
+
8.4507e-02,
|
| 885 |
+
3.0684e-02,
|
| 886 |
+
-8.7932e-02,
|
| 887 |
+
1.9927e-02,
|
| 888 |
+
-7.1788e-02,
|
| 889 |
+
9.4965e-02,
|
| 890 |
+
3.9220e-02,
|
| 891 |
+
4.5944e-02,
|
| 892 |
+
8.7249e-02,
|
| 893 |
+
3.3315e-01,
|
| 894 |
+
5.9872e-02,
|
| 895 |
+
2.6362e-02,
|
| 896 |
+
-1.7888e-01,
|
| 897 |
+
-1.6042e-02,
|
| 898 |
+
-9.4593e-02,
|
| 899 |
+
-1.7915e-01,
|
| 900 |
+
-2.9888e-02,
|
| 901 |
+
-4.3776e-02,
|
| 902 |
+
1.1388e-01,
|
| 903 |
+
2.3778e-02,
|
| 904 |
+
-4.0233e-02,
|
| 905 |
+
-4.7893e-02,
|
| 906 |
+
-4.4371e-02,
|
| 907 |
+
-2.7491e-02,
|
| 908 |
+
-9.6716e-02,
|
| 909 |
+
-2.0120e-02,
|
| 910 |
+
5.6864e-02,
|
| 911 |
+
1.8953e-02,
|
| 912 |
+
1.2741e-01,
|
| 913 |
+
-5.3045e-02,
|
| 914 |
+
3.2240e-02,
|
| 915 |
+
1.4479e-01,
|
| 916 |
+
9.5315e-02,
|
| 917 |
+
-2.7717e-02,
|
| 918 |
+
-5.7349e-02,
|
| 919 |
+
3.3824e-03,
|
| 920 |
+
-3.5642e-02,
|
| 921 |
+
-1.6905e-02,
|
| 922 |
+
-4.5765e-02,
|
| 923 |
+
1.1481e-02,
|
| 924 |
+
4.2545e-02,
|
| 925 |
+
1.2632e-02,
|
| 926 |
+
4.5401e-02,
|
| 927 |
+
7.7769e-02,
|
| 928 |
+
-1.7107e-01,
|
| 929 |
+
7.7265e-02,
|
| 930 |
+
1.3922e-02,
|
| 931 |
+
],
|
| 932 |
+
[
|
| 933 |
+
-2.5666e-02,
|
| 934 |
+
9.8268e-02,
|
| 935 |
+
2.1571e-01,
|
| 936 |
+
6.8094e-02,
|
| 937 |
+
-1.0440e-01,
|
| 938 |
+
1.4299e-01,
|
| 939 |
+
6.5751e-02,
|
| 940 |
+
-5.0693e-02,
|
| 941 |
+
-5.3796e-02,
|
| 942 |
+
1.5239e-01,
|
| 943 |
+
2.9566e-02,
|
| 944 |
+
-7.9492e-02,
|
| 945 |
+
9.3274e-02,
|
| 946 |
+
7.6112e-02,
|
| 947 |
+
-1.8187e-02,
|
| 948 |
+
-1.1190e-01,
|
| 949 |
+
9.7962e-02,
|
| 950 |
+
-2.8204e-02,
|
| 951 |
+
-8.1216e-02,
|
| 952 |
+
-5.5618e-02,
|
| 953 |
+
-6.2378e-02,
|
| 954 |
+
4.4238e-02,
|
| 955 |
+
-1.6572e-02,
|
| 956 |
+
-3.4035e-02,
|
| 957 |
+
-8.8068e-02,
|
| 958 |
+
1.4164e-02,
|
| 959 |
+
-2.6908e-02,
|
| 960 |
+
1.9650e-01,
|
| 961 |
+
6.8845e-03,
|
| 962 |
+
8.7550e-02,
|
| 963 |
+
1.7410e-01,
|
| 964 |
+
1.0088e-01,
|
| 965 |
+
-1.1340e-02,
|
| 966 |
+
3.2057e-04,
|
| 967 |
+
-5.5130e-02,
|
| 968 |
+
-2.5234e-02,
|
| 969 |
+
8.2460e-02,
|
| 970 |
+
-6.0768e-02,
|
| 971 |
+
1.2448e-01,
|
| 972 |
+
6.8736e-02,
|
| 973 |
+
4.6176e-02,
|
| 974 |
+
1.0866e-01,
|
| 975 |
+
4.9560e-02,
|
| 976 |
+
-5.8322e-02,
|
| 977 |
+
4.4106e-02,
|
| 978 |
+
2.0739e-02,
|
| 979 |
+
-9.0032e-02,
|
| 980 |
+
-5.8815e-02,
|
| 981 |
+
7.8127e-03,
|
| 982 |
+
1.7999e-01,
|
| 983 |
+
1.2519e-01,
|
| 984 |
+
7.1377e-02,
|
| 985 |
+
9.3219e-02,
|
| 986 |
+
-1.3311e-01,
|
| 987 |
+
6.0305e-02,
|
| 988 |
+
5.9400e-02,
|
| 989 |
+
-1.6119e-01,
|
| 990 |
+
5.4173e-02,
|
| 991 |
+
-5.8663e-02,
|
| 992 |
+
-4.8149e-02,
|
| 993 |
+
1.6295e-02,
|
| 994 |
+
-6.9787e-02,
|
| 995 |
+
5.7512e-03,
|
| 996 |
+
-8.9745e-03,
|
| 997 |
+
1.3492e-01,
|
| 998 |
+
3.0659e-02,
|
| 999 |
+
-6.8611e-02,
|
| 1000 |
+
2.1200e-02,
|
| 1001 |
+
8.5522e-02,
|
| 1002 |
+
-4.3482e-02,
|
| 1003 |
+
-8.4601e-02,
|
| 1004 |
+
1.4191e-01,
|
| 1005 |
+
-1.5514e-01,
|
| 1006 |
+
-5.8989e-03,
|
| 1007 |
+
-4.5591e-02,
|
| 1008 |
+
6.4905e-02,
|
| 1009 |
+
-1.3198e-01,
|
| 1010 |
+
1.3764e-01,
|
| 1011 |
+
9.5549e-02,
|
| 1012 |
+
-9.4689e-02,
|
| 1013 |
+
-1.9705e-02,
|
| 1014 |
+
2.1147e-01,
|
| 1015 |
+
-9.8519e-03,
|
| 1016 |
+
-7.7839e-02,
|
| 1017 |
+
6.1447e-02,
|
| 1018 |
+
-6.4708e-02,
|
| 1019 |
+
3.1579e-03,
|
| 1020 |
+
7.6588e-02,
|
| 1021 |
+
-1.2452e-01,
|
| 1022 |
+
-6.1076e-02,
|
| 1023 |
+
2.5150e-01,
|
| 1024 |
+
2.3101e-02,
|
| 1025 |
+
-1.3632e-02,
|
| 1026 |
+
-8.5695e-02,
|
| 1027 |
+
-8.5841e-02,
|
| 1028 |
+
-1.3152e-01,
|
| 1029 |
+
-1.5294e-01,
|
| 1030 |
+
-4.4509e-03,
|
| 1031 |
+
8.6619e-02,
|
| 1032 |
+
-1.0974e-02,
|
| 1033 |
+
-3.9592e-02,
|
| 1034 |
+
-3.0472e-02,
|
| 1035 |
+
-1.4011e-01,
|
| 1036 |
+
8.6485e-03,
|
| 1037 |
+
-1.3633e-02,
|
| 1038 |
+
-1.7940e-02,
|
| 1039 |
+
3.3016e-02,
|
| 1040 |
+
-5.7245e-02,
|
| 1041 |
+
1.0200e-01,
|
| 1042 |
+
1.2807e-01,
|
| 1043 |
+
1.5249e-02,
|
| 1044 |
+
-1.2197e-02,
|
| 1045 |
+
-1.6867e-02,
|
| 1046 |
+
3.4516e-02,
|
| 1047 |
+
-9.0908e-02,
|
| 1048 |
+
-2.6167e-02,
|
| 1049 |
+
2.2975e-01,
|
| 1050 |
+
4.2693e-02,
|
| 1051 |
+
2.5415e-03,
|
| 1052 |
+
7.1921e-03,
|
| 1053 |
+
1.2855e-01,
|
| 1054 |
+
5.5747e-03,
|
| 1055 |
+
-2.7843e-02,
|
| 1056 |
+
2.4283e-02,
|
| 1057 |
+
-1.3484e-02,
|
| 1058 |
+
-1.5948e-01,
|
| 1059 |
+
2.1127e-02,
|
| 1060 |
+
3.8017e-02,
|
| 1061 |
+
],
|
| 1062 |
+
[
|
| 1063 |
+
5.8410e-02,
|
| 1064 |
+
3.7501e-02,
|
| 1065 |
+
1.7189e-01,
|
| 1066 |
+
4.5894e-02,
|
| 1067 |
+
-6.7739e-02,
|
| 1068 |
+
1.1421e-01,
|
| 1069 |
+
4.6982e-02,
|
| 1070 |
+
-1.2963e-01,
|
| 1071 |
+
-4.2804e-02,
|
| 1072 |
+
1.2137e-01,
|
| 1073 |
+
1.0761e-01,
|
| 1074 |
+
-7.2615e-02,
|
| 1075 |
+
1.1811e-01,
|
| 1076 |
+
1.1291e-01,
|
| 1077 |
+
-1.6041e-01,
|
| 1078 |
+
-6.6820e-02,
|
| 1079 |
+
1.9071e-01,
|
| 1080 |
+
-3.6201e-02,
|
| 1081 |
+
-1.0659e-01,
|
| 1082 |
+
-3.3226e-02,
|
| 1083 |
+
-2.6535e-02,
|
| 1084 |
+
7.8536e-02,
|
| 1085 |
+
-3.2975e-02,
|
| 1086 |
+
1.3015e-02,
|
| 1087 |
+
-1.0903e-01,
|
| 1088 |
+
-1.2502e-02,
|
| 1089 |
+
-7.0142e-02,
|
| 1090 |
+
1.6872e-01,
|
| 1091 |
+
-3.7569e-02,
|
| 1092 |
+
2.2090e-01,
|
| 1093 |
+
1.5620e-01,
|
| 1094 |
+
9.5620e-02,
|
| 1095 |
+
-7.9306e-02,
|
| 1096 |
+
7.8558e-02,
|
| 1097 |
+
-6.6709e-02,
|
| 1098 |
+
-6.6446e-02,
|
| 1099 |
+
3.1198e-02,
|
| 1100 |
+
-4.8808e-02,
|
| 1101 |
+
6.7798e-02,
|
| 1102 |
+
-4.9524e-02,
|
| 1103 |
+
1.2496e-01,
|
| 1104 |
+
3.1661e-02,
|
| 1105 |
+
4.0690e-02,
|
| 1106 |
+
-1.1341e-02,
|
| 1107 |
+
2.9852e-03,
|
| 1108 |
+
3.6166e-02,
|
| 1109 |
+
-1.1723e-01,
|
| 1110 |
+
-8.2746e-02,
|
| 1111 |
+
1.2874e-01,
|
| 1112 |
+
1.0894e-01,
|
| 1113 |
+
7.6219e-02,
|
| 1114 |
+
5.5564e-02,
|
| 1115 |
+
4.3571e-02,
|
| 1116 |
+
-1.4745e-01,
|
| 1117 |
+
5.1090e-02,
|
| 1118 |
+
-6.8233e-04,
|
| 1119 |
+
-1.7107e-01,
|
| 1120 |
+
-2.5612e-02,
|
| 1121 |
+
1.9185e-02,
|
| 1122 |
+
3.4466e-03,
|
| 1123 |
+
-2.5362e-02,
|
| 1124 |
+
-3.4807e-02,
|
| 1125 |
+
8.1003e-02,
|
| 1126 |
+
-2.1582e-02,
|
| 1127 |
+
1.1581e-01,
|
| 1128 |
+
-5.5891e-04,
|
| 1129 |
+
4.2455e-02,
|
| 1130 |
+
6.3277e-02,
|
| 1131 |
+
7.9868e-02,
|
| 1132 |
+
-2.0369e-02,
|
| 1133 |
+
-7.6229e-02,
|
| 1134 |
+
1.2525e-01,
|
| 1135 |
+
-1.4795e-01,
|
| 1136 |
+
5.8798e-03,
|
| 1137 |
+
-2.8584e-02,
|
| 1138 |
+
-3.2508e-04,
|
| 1139 |
+
-5.5666e-02,
|
| 1140 |
+
7.1217e-02,
|
| 1141 |
+
1.3122e-01,
|
| 1142 |
+
-1.8671e-02,
|
| 1143 |
+
-6.6402e-02,
|
| 1144 |
+
8.1978e-02,
|
| 1145 |
+
-5.5194e-02,
|
| 1146 |
+
-1.7259e-02,
|
| 1147 |
+
7.1373e-02,
|
| 1148 |
+
-2.4721e-02,
|
| 1149 |
+
1.0176e-01,
|
| 1150 |
+
1.7447e-02,
|
| 1151 |
+
-8.2872e-02,
|
| 1152 |
+
4.7707e-02,
|
| 1153 |
+
2.9338e-01,
|
| 1154 |
+
3.0481e-02,
|
| 1155 |
+
1.3437e-02,
|
| 1156 |
+
-1.1888e-01,
|
| 1157 |
+
-6.1243e-02,
|
| 1158 |
+
-8.7197e-02,
|
| 1159 |
+
-1.1085e-01,
|
| 1160 |
+
3.2847e-03,
|
| 1161 |
+
1.0611e-02,
|
| 1162 |
+
1.2908e-01,
|
| 1163 |
+
-2.9064e-02,
|
| 1164 |
+
4.5522e-03,
|
| 1165 |
+
-7.8045e-02,
|
| 1166 |
+
-1.4551e-02,
|
| 1167 |
+
-3.3958e-02,
|
| 1168 |
+
-1.3626e-01,
|
| 1169 |
+
1.0859e-01,
|
| 1170 |
+
-7.3438e-03,
|
| 1171 |
+
9.5942e-02,
|
| 1172 |
+
1.4176e-01,
|
| 1173 |
+
7.3675e-02,
|
| 1174 |
+
-2.3085e-03,
|
| 1175 |
+
-1.1689e-02,
|
| 1176 |
+
6.1119e-02,
|
| 1177 |
+
-9.3085e-02,
|
| 1178 |
+
-1.9003e-03,
|
| 1179 |
+
1.9013e-01,
|
| 1180 |
+
-2.5321e-02,
|
| 1181 |
+
-7.0616e-02,
|
| 1182 |
+
-3.7145e-02,
|
| 1183 |
+
1.2449e-01,
|
| 1184 |
+
5.3496e-02,
|
| 1185 |
+
6.4021e-02,
|
| 1186 |
+
2.2668e-02,
|
| 1187 |
+
7.3348e-02,
|
| 1188 |
+
-1.7717e-01,
|
| 1189 |
+
8.7206e-02,
|
| 1190 |
+
-9.0490e-03,
|
| 1191 |
+
],
|
| 1192 |
+
[
|
| 1193 |
+
1.0227e-01,
|
| 1194 |
+
4.4796e-02,
|
| 1195 |
+
4.0916e-02,
|
| 1196 |
+
1.2557e-01,
|
| 1197 |
+
6.2699e-02,
|
| 1198 |
+
8.8194e-02,
|
| 1199 |
+
1.0194e-02,
|
| 1200 |
+
-1.8886e-01,
|
| 1201 |
+
-2.6260e-02,
|
| 1202 |
+
1.8107e-01,
|
| 1203 |
+
1.1127e-01,
|
| 1204 |
+
-4.9960e-03,
|
| 1205 |
+
8.2291e-02,
|
| 1206 |
+
6.0932e-02,
|
| 1207 |
+
-1.3735e-01,
|
| 1208 |
+
-8.1350e-02,
|
| 1209 |
+
1.2948e-01,
|
| 1210 |
+
1.0171e-01,
|
| 1211 |
+
-7.5950e-02,
|
| 1212 |
+
4.7169e-02,
|
| 1213 |
+
3.5525e-03,
|
| 1214 |
+
-1.4790e-02,
|
| 1215 |
+
-3.9063e-02,
|
| 1216 |
+
-1.9754e-02,
|
| 1217 |
+
-4.6450e-02,
|
| 1218 |
+
4.9071e-03,
|
| 1219 |
+
-3.5914e-02,
|
| 1220 |
+
1.7644e-01,
|
| 1221 |
+
4.1860e-02,
|
| 1222 |
+
1.0857e-01,
|
| 1223 |
+
8.5257e-02,
|
| 1224 |
+
1.0368e-01,
|
| 1225 |
+
-1.7223e-01,
|
| 1226 |
+
4.6316e-02,
|
| 1227 |
+
-3.9480e-02,
|
| 1228 |
+
-9.5817e-02,
|
| 1229 |
+
1.5301e-03,
|
| 1230 |
+
-4.5519e-02,
|
| 1231 |
+
1.2380e-01,
|
| 1232 |
+
-3.0402e-02,
|
| 1233 |
+
4.9047e-02,
|
| 1234 |
+
3.4955e-02,
|
| 1235 |
+
-1.3018e-02,
|
| 1236 |
+
7.4193e-02,
|
| 1237 |
+
-3.0426e-02,
|
| 1238 |
+
1.8414e-02,
|
| 1239 |
+
-1.6606e-02,
|
| 1240 |
+
-1.6301e-01,
|
| 1241 |
+
1.5784e-01,
|
| 1242 |
+
1.3759e-01,
|
| 1243 |
+
3.1906e-02,
|
| 1244 |
+
2.9389e-02,
|
| 1245 |
+
-9.4501e-02,
|
| 1246 |
+
-1.9930e-01,
|
| 1247 |
+
1.3336e-01,
|
| 1248 |
+
3.0685e-02,
|
| 1249 |
+
-7.3809e-02,
|
| 1250 |
+
6.2165e-02,
|
| 1251 |
+
7.3050e-02,
|
| 1252 |
+
3.2870e-02,
|
| 1253 |
+
-1.2857e-01,
|
| 1254 |
+
-7.5806e-04,
|
| 1255 |
+
1.3985e-01,
|
| 1256 |
+
-5.5108e-02,
|
| 1257 |
+
9.2220e-02,
|
| 1258 |
+
7.2490e-02,
|
| 1259 |
+
-2.6251e-02,
|
| 1260 |
+
3.4508e-02,
|
| 1261 |
+
-3.1215e-02,
|
| 1262 |
+
-8.1111e-02,
|
| 1263 |
+
1.4316e-02,
|
| 1264 |
+
1.2390e-01,
|
| 1265 |
+
-9.6291e-03,
|
| 1266 |
+
6.4214e-02,
|
| 1267 |
+
-9.6013e-02,
|
| 1268 |
+
7.5809e-02,
|
| 1269 |
+
-1.5899e-01,
|
| 1270 |
+
8.6961e-02,
|
| 1271 |
+
1.5239e-03,
|
| 1272 |
+
-5.6370e-02,
|
| 1273 |
+
-4.3367e-02,
|
| 1274 |
+
1.5813e-02,
|
| 1275 |
+
9.7189e-04,
|
| 1276 |
+
-5.2946e-02,
|
| 1277 |
+
4.5950e-02,
|
| 1278 |
+
-1.0028e-01,
|
| 1279 |
+
1.1108e-01,
|
| 1280 |
+
9.0491e-03,
|
| 1281 |
+
-3.5540e-02,
|
| 1282 |
+
-1.2020e-02,
|
| 1283 |
+
2.2980e-01,
|
| 1284 |
+
2.7125e-02,
|
| 1285 |
+
-2.4191e-02,
|
| 1286 |
+
-1.1363e-01,
|
| 1287 |
+
-1.0109e-01,
|
| 1288 |
+
-1.4781e-01,
|
| 1289 |
+
-4.7656e-02,
|
| 1290 |
+
3.9481e-02,
|
| 1291 |
+
5.4198e-02,
|
| 1292 |
+
8.2908e-02,
|
| 1293 |
+
1.4034e-02,
|
| 1294 |
+
-1.8492e-02,
|
| 1295 |
+
-6.8612e-02,
|
| 1296 |
+
-4.8741e-02,
|
| 1297 |
+
1.1223e-02,
|
| 1298 |
+
3.9220e-02,
|
| 1299 |
+
5.4551e-04,
|
| 1300 |
+
6.5554e-02,
|
| 1301 |
+
4.3087e-02,
|
| 1302 |
+
1.4678e-01,
|
| 1303 |
+
-4.4496e-02,
|
| 1304 |
+
6.2379e-02,
|
| 1305 |
+
4.7876e-02,
|
| 1306 |
+
7.0156e-02,
|
| 1307 |
+
-6.4684e-02,
|
| 1308 |
+
6.1076e-02,
|
| 1309 |
+
1.4685e-01,
|
| 1310 |
+
-6.3639e-02,
|
| 1311 |
+
-8.7487e-02,
|
| 1312 |
+
-1.3756e-02,
|
| 1313 |
+
1.2724e-01,
|
| 1314 |
+
1.7404e-01,
|
| 1315 |
+
6.7980e-02,
|
| 1316 |
+
6.8036e-02,
|
| 1317 |
+
1.9786e-01,
|
| 1318 |
+
-9.2910e-02,
|
| 1319 |
+
1.9158e-01,
|
| 1320 |
+
4.2686e-02,
|
| 1321 |
+
],
|
| 1322 |
+
[
|
| 1323 |
+
4.7626e-02,
|
| 1324 |
+
9.3338e-02,
|
| 1325 |
+
9.8020e-02,
|
| 1326 |
+
9.2408e-02,
|
| 1327 |
+
1.8267e-02,
|
| 1328 |
+
1.9572e-02,
|
| 1329 |
+
1.1056e-01,
|
| 1330 |
+
-1.2639e-01,
|
| 1331 |
+
-3.1999e-02,
|
| 1332 |
+
1.3731e-01,
|
| 1333 |
+
1.4826e-01,
|
| 1334 |
+
-6.7136e-02,
|
| 1335 |
+
8.9095e-02,
|
| 1336 |
+
1.9683e-01,
|
| 1337 |
+
-6.5839e-02,
|
| 1338 |
+
-1.0708e-01,
|
| 1339 |
+
1.4414e-01,
|
| 1340 |
+
4.7389e-02,
|
| 1341 |
+
-7.9921e-02,
|
| 1342 |
+
2.7793e-02,
|
| 1343 |
+
9.7240e-02,
|
| 1344 |
+
3.8000e-03,
|
| 1345 |
+
-4.2359e-02,
|
| 1346 |
+
5.9870e-02,
|
| 1347 |
+
-8.2957e-02,
|
| 1348 |
+
-2.1429e-02,
|
| 1349 |
+
-5.1302e-02,
|
| 1350 |
+
7.6202e-02,
|
| 1351 |
+
3.5426e-02,
|
| 1352 |
+
8.1509e-02,
|
| 1353 |
+
1.0849e-01,
|
| 1354 |
+
2.1857e-01,
|
| 1355 |
+
-9.1445e-02,
|
| 1356 |
+
1.1869e-01,
|
| 1357 |
+
-1.1225e-02,
|
| 1358 |
+
-1.6530e-01,
|
| 1359 |
+
2.9216e-02,
|
| 1360 |
+
-7.2792e-02,
|
| 1361 |
+
2.9544e-02,
|
| 1362 |
+
5.3102e-02,
|
| 1363 |
+
2.7746e-02,
|
| 1364 |
+
1.8145e-01,
|
| 1365 |
+
4.4050e-02,
|
| 1366 |
+
8.2549e-02,
|
| 1367 |
+
2.3603e-02,
|
| 1368 |
+
1.1494e-02,
|
| 1369 |
+
-9.1516e-02,
|
| 1370 |
+
-6.2333e-02,
|
| 1371 |
+
1.0970e-01,
|
| 1372 |
+
1.4544e-01,
|
| 1373 |
+
-2.3549e-02,
|
| 1374 |
+
3.8348e-02,
|
| 1375 |
+
-8.8504e-03,
|
| 1376 |
+
-1.6986e-01,
|
| 1377 |
+
5.3215e-02,
|
| 1378 |
+
4.0085e-02,
|
| 1379 |
+
-1.4667e-01,
|
| 1380 |
+
8.6047e-02,
|
| 1381 |
+
4.7751e-02,
|
| 1382 |
+
-9.0753e-03,
|
| 1383 |
+
-8.0938e-02,
|
| 1384 |
+
7.1735e-02,
|
| 1385 |
+
1.1711e-01,
|
| 1386 |
+
-4.2525e-02,
|
| 1387 |
+
9.4244e-02,
|
| 1388 |
+
6.2260e-02,
|
| 1389 |
+
-8.4798e-02,
|
| 1390 |
+
-6.2766e-02,
|
| 1391 |
+
6.1025e-02,
|
| 1392 |
+
-7.7480e-02,
|
| 1393 |
+
-5.3010e-02,
|
| 1394 |
+
1.0182e-01,
|
| 1395 |
+
-7.1081e-03,
|
| 1396 |
+
1.4029e-01,
|
| 1397 |
+
-8.2788e-02,
|
| 1398 |
+
3.0182e-02,
|
| 1399 |
+
-1.4279e-01,
|
| 1400 |
+
4.7882e-02,
|
| 1401 |
+
3.2736e-02,
|
| 1402 |
+
1.0058e-02,
|
| 1403 |
+
-1.2673e-02,
|
| 1404 |
+
3.2723e-02,
|
| 1405 |
+
5.7034e-02,
|
| 1406 |
+
-2.0343e-02,
|
| 1407 |
+
-6.3037e-03,
|
| 1408 |
+
6.8914e-03,
|
| 1409 |
+
2.8643e-02,
|
| 1410 |
+
8.2739e-02,
|
| 1411 |
+
-2.5124e-02,
|
| 1412 |
+
-7.0611e-02,
|
| 1413 |
+
2.7142e-01,
|
| 1414 |
+
-1.6370e-02,
|
| 1415 |
+
1.1240e-02,
|
| 1416 |
+
-1.5776e-01,
|
| 1417 |
+
-8.8755e-02,
|
| 1418 |
+
-1.2389e-01,
|
| 1419 |
+
-2.5785e-02,
|
| 1420 |
+
-3.1258e-02,
|
| 1421 |
+
2.2023e-02,
|
| 1422 |
+
8.5497e-02,
|
| 1423 |
+
6.8360e-02,
|
| 1424 |
+
9.6662e-03,
|
| 1425 |
+
-1.2843e-01,
|
| 1426 |
+
-7.4122e-02,
|
| 1427 |
+
7.1105e-02,
|
| 1428 |
+
5.8334e-02,
|
| 1429 |
+
-1.8609e-02,
|
| 1430 |
+
7.2775e-02,
|
| 1431 |
+
-1.1696e-03,
|
| 1432 |
+
1.3165e-01,
|
| 1433 |
+
-4.7326e-02,
|
| 1434 |
+
6.8737e-02,
|
| 1435 |
+
-2.3211e-02,
|
| 1436 |
+
5.5425e-02,
|
| 1437 |
+
-6.8077e-02,
|
| 1438 |
+
-7.3743e-04,
|
| 1439 |
+
1.6215e-01,
|
| 1440 |
+
-4.9965e-02,
|
| 1441 |
+
-6.8493e-02,
|
| 1442 |
+
-6.8358e-03,
|
| 1443 |
+
9.9518e-02,
|
| 1444 |
+
1.5627e-01,
|
| 1445 |
+
1.3100e-01,
|
| 1446 |
+
9.0073e-03,
|
| 1447 |
+
1.8023e-01,
|
| 1448 |
+
-2.7992e-02,
|
| 1449 |
+
1.3087e-01,
|
| 1450 |
+
7.5672e-02,
|
| 1451 |
+
],
|
| 1452 |
+
[
|
| 1453 |
+
9.0390e-03,
|
| 1454 |
+
1.3137e-01,
|
| 1455 |
+
4.6586e-02,
|
| 1456 |
+
1.1836e-01,
|
| 1457 |
+
1.1406e-01,
|
| 1458 |
+
-7.3655e-02,
|
| 1459 |
+
-1.4340e-02,
|
| 1460 |
+
-1.4285e-01,
|
| 1461 |
+
2.0426e-02,
|
| 1462 |
+
1.3532e-01,
|
| 1463 |
+
1.3353e-01,
|
| 1464 |
+
-4.7242e-02,
|
| 1465 |
+
2.6449e-02,
|
| 1466 |
+
2.0707e-02,
|
| 1467 |
+
-7.5049e-02,
|
| 1468 |
+
-4.4098e-02,
|
| 1469 |
+
1.4599e-01,
|
| 1470 |
+
1.1299e-01,
|
| 1471 |
+
-2.2097e-02,
|
| 1472 |
+
8.4679e-02,
|
| 1473 |
+
5.8946e-02,
|
| 1474 |
+
2.1213e-02,
|
| 1475 |
+
-5.8343e-03,
|
| 1476 |
+
-4.5902e-02,
|
| 1477 |
+
-6.1018e-02,
|
| 1478 |
+
4.4368e-02,
|
| 1479 |
+
-5.7242e-02,
|
| 1480 |
+
1.4734e-01,
|
| 1481 |
+
-2.6191e-02,
|
| 1482 |
+
8.6116e-02,
|
| 1483 |
+
4.6004e-02,
|
| 1484 |
+
9.4532e-02,
|
| 1485 |
+
-1.7424e-01,
|
| 1486 |
+
1.3697e-01,
|
| 1487 |
+
4.6544e-02,
|
| 1488 |
+
-1.1718e-01,
|
| 1489 |
+
8.2567e-02,
|
| 1490 |
+
-3.1494e-02,
|
| 1491 |
+
6.2073e-02,
|
| 1492 |
+
-4.6328e-02,
|
| 1493 |
+
1.0782e-02,
|
| 1494 |
+
6.6071e-02,
|
| 1495 |
+
9.6953e-03,
|
| 1496 |
+
2.0415e-02,
|
| 1497 |
+
-7.0939e-02,
|
| 1498 |
+
-3.1883e-02,
|
| 1499 |
+
-4.9926e-02,
|
| 1500 |
+
-1.2694e-01,
|
| 1501 |
+
1.6351e-01,
|
| 1502 |
+
1.1670e-01,
|
| 1503 |
+
3.8149e-02,
|
| 1504 |
+
7.2657e-02,
|
| 1505 |
+
-1.3930e-01,
|
| 1506 |
+
-1.6682e-01,
|
| 1507 |
+
1.2471e-01,
|
| 1508 |
+
1.9094e-02,
|
| 1509 |
+
-6.1618e-02,
|
| 1510 |
+
5.8628e-02,
|
| 1511 |
+
1.8804e-03,
|
| 1512 |
+
-9.8104e-03,
|
| 1513 |
+
-1.8998e-01,
|
| 1514 |
+
1.4179e-02,
|
| 1515 |
+
1.4856e-01,
|
| 1516 |
+
-4.2194e-02,
|
| 1517 |
+
5.0934e-02,
|
| 1518 |
+
7.4201e-02,
|
| 1519 |
+
1.5546e-02,
|
| 1520 |
+
2.3192e-02,
|
| 1521 |
+
-5.5886e-02,
|
| 1522 |
+
-4.3618e-02,
|
| 1523 |
+
3.6677e-02,
|
| 1524 |
+
1.2750e-01,
|
| 1525 |
+
2.1240e-02,
|
| 1526 |
+
9.5849e-02,
|
| 1527 |
+
-1.2006e-01,
|
| 1528 |
+
6.0424e-02,
|
| 1529 |
+
-1.6516e-01,
|
| 1530 |
+
7.8015e-02,
|
| 1531 |
+
-7.6026e-02,
|
| 1532 |
+
-1.6711e-02,
|
| 1533 |
+
-3.3572e-02,
|
| 1534 |
+
4.3704e-02,
|
| 1535 |
+
1.2728e-02,
|
| 1536 |
+
-6.9630e-02,
|
| 1537 |
+
4.1065e-02,
|
| 1538 |
+
-8.6589e-02,
|
| 1539 |
+
1.1581e-01,
|
| 1540 |
+
2.2666e-02,
|
| 1541 |
+
-5.1476e-02,
|
| 1542 |
+
2.2756e-02,
|
| 1543 |
+
1.9309e-01,
|
| 1544 |
+
7.0417e-02,
|
| 1545 |
+
8.9253e-03,
|
| 1546 |
+
-1.3546e-01,
|
| 1547 |
+
-7.7783e-02,
|
| 1548 |
+
-1.5058e-01,
|
| 1549 |
+
-4.7874e-02,
|
| 1550 |
+
3.3498e-02,
|
| 1551 |
+
6.4585e-02,
|
| 1552 |
+
7.8633e-02,
|
| 1553 |
+
1.0162e-01,
|
| 1554 |
+
4.5821e-02,
|
| 1555 |
+
-2.8424e-02,
|
| 1556 |
+
4.4524e-02,
|
| 1557 |
+
4.6649e-02,
|
| 1558 |
+
4.5805e-02,
|
| 1559 |
+
8.9723e-02,
|
| 1560 |
+
3.7597e-02,
|
| 1561 |
+
-6.8016e-03,
|
| 1562 |
+
1.1727e-01,
|
| 1563 |
+
-6.6387e-02,
|
| 1564 |
+
3.4958e-02,
|
| 1565 |
+
4.0205e-02,
|
| 1566 |
+
7.5854e-02,
|
| 1567 |
+
-5.1322e-02,
|
| 1568 |
+
6.0060e-02,
|
| 1569 |
+
1.4631e-01,
|
| 1570 |
+
-1.1550e-01,
|
| 1571 |
+
-1.5388e-01,
|
| 1572 |
+
6.0975e-03,
|
| 1573 |
+
1.2013e-01,
|
| 1574 |
+
2.1669e-01,
|
| 1575 |
+
4.8245e-02,
|
| 1576 |
+
8.4634e-02,
|
| 1577 |
+
1.4934e-01,
|
| 1578 |
+
-1.2099e-01,
|
| 1579 |
+
1.6673e-01,
|
| 1580 |
+
6.2539e-02,
|
| 1581 |
+
],
|
| 1582 |
+
[
|
| 1583 |
+
1.6222e-01,
|
| 1584 |
+
7.5644e-03,
|
| 1585 |
+
1.0667e-01,
|
| 1586 |
+
8.3084e-02,
|
| 1587 |
+
5.1888e-02,
|
| 1588 |
+
8.7477e-02,
|
| 1589 |
+
-1.1550e-01,
|
| 1590 |
+
-4.7037e-02,
|
| 1591 |
+
-3.9418e-02,
|
| 1592 |
+
8.0987e-02,
|
| 1593 |
+
1.2812e-01,
|
| 1594 |
+
-6.6527e-02,
|
| 1595 |
+
6.5405e-02,
|
| 1596 |
+
5.2723e-03,
|
| 1597 |
+
-6.2940e-02,
|
| 1598 |
+
-5.8805e-02,
|
| 1599 |
+
2.8526e-02,
|
| 1600 |
+
4.0631e-02,
|
| 1601 |
+
9.8513e-02,
|
| 1602 |
+
-2.8448e-02,
|
| 1603 |
+
9.2361e-02,
|
| 1604 |
+
6.9724e-02,
|
| 1605 |
+
-1.1792e-01,
|
| 1606 |
+
-1.4806e-02,
|
| 1607 |
+
-6.6172e-02,
|
| 1608 |
+
5.9468e-02,
|
| 1609 |
+
-1.8325e-01,
|
| 1610 |
+
3.2851e-02,
|
| 1611 |
+
-2.7042e-02,
|
| 1612 |
+
1.7569e-01,
|
| 1613 |
+
1.9061e-01,
|
| 1614 |
+
4.1868e-02,
|
| 1615 |
+
-1.4116e-01,
|
| 1616 |
+
-1.6780e-02,
|
| 1617 |
+
-6.2881e-02,
|
| 1618 |
+
-9.4655e-02,
|
| 1619 |
+
5.1488e-02,
|
| 1620 |
+
-3.6501e-03,
|
| 1621 |
+
5.6754e-02,
|
| 1622 |
+
-6.3285e-03,
|
| 1623 |
+
9.2234e-02,
|
| 1624 |
+
-1.0761e-01,
|
| 1625 |
+
-5.5392e-02,
|
| 1626 |
+
7.5249e-02,
|
| 1627 |
+
8.7539e-02,
|
| 1628 |
+
4.3377e-02,
|
| 1629 |
+
3.2473e-03,
|
| 1630 |
+
-1.0990e-01,
|
| 1631 |
+
5.2611e-02,
|
| 1632 |
+
3.4955e-02,
|
| 1633 |
+
1.1722e-01,
|
| 1634 |
+
4.0339e-02,
|
| 1635 |
+
-9.6605e-02,
|
| 1636 |
+
-9.3660e-02,
|
| 1637 |
+
9.6494e-02,
|
| 1638 |
+
-1.4790e-02,
|
| 1639 |
+
-5.7770e-02,
|
| 1640 |
+
4.3192e-02,
|
| 1641 |
+
-8.1741e-02,
|
| 1642 |
+
-4.0909e-02,
|
| 1643 |
+
-9.5212e-02,
|
| 1644 |
+
-1.2459e-01,
|
| 1645 |
+
3.6241e-02,
|
| 1646 |
+
-1.2878e-01,
|
| 1647 |
+
1.1544e-01,
|
| 1648 |
+
3.6392e-03,
|
| 1649 |
+
-7.7986e-03,
|
| 1650 |
+
8.2339e-02,
|
| 1651 |
+
1.4319e-01,
|
| 1652 |
+
-5.8374e-02,
|
| 1653 |
+
1.2483e-01,
|
| 1654 |
+
5.6826e-02,
|
| 1655 |
+
-6.2649e-02,
|
| 1656 |
+
4.5884e-02,
|
| 1657 |
+
-1.8261e-01,
|
| 1658 |
+
-9.1633e-02,
|
| 1659 |
+
-1.9414e-01,
|
| 1660 |
+
2.8376e-02,
|
| 1661 |
+
9.5654e-02,
|
| 1662 |
+
-1.3532e-01,
|
| 1663 |
+
2.1669e-03,
|
| 1664 |
+
7.9960e-02,
|
| 1665 |
+
5.0917e-02,
|
| 1666 |
+
-5.4874e-02,
|
| 1667 |
+
7.6823e-02,
|
| 1668 |
+
-1.3932e-01,
|
| 1669 |
+
1.2431e-01,
|
| 1670 |
+
1.3001e-01,
|
| 1671 |
+
-6.0069e-02,
|
| 1672 |
+
2.6470e-02,
|
| 1673 |
+
2.2378e-01,
|
| 1674 |
+
2.7335e-02,
|
| 1675 |
+
1.6487e-02,
|
| 1676 |
+
-9.6473e-02,
|
| 1677 |
+
8.3110e-02,
|
| 1678 |
+
-8.8776e-02,
|
| 1679 |
+
-6.2299e-02,
|
| 1680 |
+
4.0821e-02,
|
| 1681 |
+
6.5279e-02,
|
| 1682 |
+
8.4030e-02,
|
| 1683 |
+
-4.9298e-02,
|
| 1684 |
+
-3.7441e-02,
|
| 1685 |
+
-4.9233e-02,
|
| 1686 |
+
-1.9428e-03,
|
| 1687 |
+
-1.9763e-02,
|
| 1688 |
+
-9.1249e-02,
|
| 1689 |
+
1.1593e-01,
|
| 1690 |
+
6.6291e-03,
|
| 1691 |
+
-1.0686e-01,
|
| 1692 |
+
5.9383e-02,
|
| 1693 |
+
-3.1088e-02,
|
| 1694 |
+
-1.9844e-03,
|
| 1695 |
+
2.5891e-02,
|
| 1696 |
+
1.3471e-01,
|
| 1697 |
+
-3.5624e-02,
|
| 1698 |
+
1.2647e-01,
|
| 1699 |
+
6.7167e-02,
|
| 1700 |
+
-1.8682e-02,
|
| 1701 |
+
-2.4806e-02,
|
| 1702 |
+
-1.1453e-02,
|
| 1703 |
+
9.6992e-02,
|
| 1704 |
+
1.2253e-01,
|
| 1705 |
+
5.6707e-02,
|
| 1706 |
+
1.0860e-02,
|
| 1707 |
+
2.4775e-01,
|
| 1708 |
+
-8.8641e-02,
|
| 1709 |
+
1.1375e-01,
|
| 1710 |
+
6.9383e-02,
|
| 1711 |
+
],
|
| 1712 |
+
[
|
| 1713 |
+
1.4724e-01,
|
| 1714 |
+
3.7511e-02,
|
| 1715 |
+
1.1238e-01,
|
| 1716 |
+
6.3809e-02,
|
| 1717 |
+
1.8174e-03,
|
| 1718 |
+
8.4854e-02,
|
| 1719 |
+
-7.8965e-02,
|
| 1720 |
+
-3.1542e-02,
|
| 1721 |
+
-3.7643e-02,
|
| 1722 |
+
1.0136e-01,
|
| 1723 |
+
1.5837e-01,
|
| 1724 |
+
-7.5701e-02,
|
| 1725 |
+
1.0313e-01,
|
| 1726 |
+
2.2795e-02,
|
| 1727 |
+
-1.1227e-01,
|
| 1728 |
+
-4.3783e-02,
|
| 1729 |
+
4.6561e-02,
|
| 1730 |
+
4.1225e-02,
|
| 1731 |
+
7.4273e-02,
|
| 1732 |
+
-4.8200e-02,
|
| 1733 |
+
2.7666e-02,
|
| 1734 |
+
5.1417e-02,
|
| 1735 |
+
-1.3928e-01,
|
| 1736 |
+
2.0020e-02,
|
| 1737 |
+
-9.3673e-02,
|
| 1738 |
+
5.1440e-02,
|
| 1739 |
+
-2.0076e-01,
|
| 1740 |
+
1.0715e-01,
|
| 1741 |
+
-3.0323e-02,
|
| 1742 |
+
1.7241e-01,
|
| 1743 |
+
1.9730e-01,
|
| 1744 |
+
7.7685e-02,
|
| 1745 |
+
-1.5949e-01,
|
| 1746 |
+
4.8495e-02,
|
| 1747 |
+
-8.0068e-02,
|
| 1748 |
+
-7.1965e-02,
|
| 1749 |
+
8.7222e-02,
|
| 1750 |
+
-4.8383e-02,
|
| 1751 |
+
7.0627e-02,
|
| 1752 |
+
3.9791e-03,
|
| 1753 |
+
7.0469e-02,
|
| 1754 |
+
-8.6697e-02,
|
| 1755 |
+
-3.7149e-02,
|
| 1756 |
+
7.9965e-02,
|
| 1757 |
+
8.8967e-02,
|
| 1758 |
+
5.3325e-02,
|
| 1759 |
+
-5.6073e-03,
|
| 1760 |
+
-1.1336e-01,
|
| 1761 |
+
1.0338e-01,
|
| 1762 |
+
2.3824e-02,
|
| 1763 |
+
6.9393e-02,
|
| 1764 |
+
6.1018e-02,
|
| 1765 |
+
-7.2880e-02,
|
| 1766 |
+
-6.6328e-02,
|
| 1767 |
+
8.9040e-02,
|
| 1768 |
+
-8.8268e-03,
|
| 1769 |
+
-7.5720e-02,
|
| 1770 |
+
3.7544e-02,
|
| 1771 |
+
-8.3740e-02,
|
| 1772 |
+
-4.7977e-02,
|
| 1773 |
+
-1.2425e-01,
|
| 1774 |
+
-1.0304e-01,
|
| 1775 |
+
-3.7850e-03,
|
| 1776 |
+
-1.1540e-01,
|
| 1777 |
+
1.0803e-01,
|
| 1778 |
+
2.5964e-02,
|
| 1779 |
+
-1.0915e-02,
|
| 1780 |
+
1.1758e-01,
|
| 1781 |
+
1.6561e-01,
|
| 1782 |
+
-4.5171e-02,
|
| 1783 |
+
1.1272e-01,
|
| 1784 |
+
6.0721e-02,
|
| 1785 |
+
-9.6027e-02,
|
| 1786 |
+
6.0908e-02,
|
| 1787 |
+
-1.6545e-01,
|
| 1788 |
+
-6.5444e-02,
|
| 1789 |
+
-1.6802e-01,
|
| 1790 |
+
2.5850e-02,
|
| 1791 |
+
1.2434e-01,
|
| 1792 |
+
-1.2358e-01,
|
| 1793 |
+
-5.2647e-04,
|
| 1794 |
+
1.2329e-01,
|
| 1795 |
+
6.3928e-02,
|
| 1796 |
+
-5.5478e-02,
|
| 1797 |
+
5.4642e-02,
|
| 1798 |
+
-1.0372e-01,
|
| 1799 |
+
1.0955e-01,
|
| 1800 |
+
1.1810e-01,
|
| 1801 |
+
-7.7028e-02,
|
| 1802 |
+
5.0302e-02,
|
| 1803 |
+
2.7576e-01,
|
| 1804 |
+
6.4704e-02,
|
| 1805 |
+
3.7824e-03,
|
| 1806 |
+
-8.3016e-02,
|
| 1807 |
+
6.7355e-02,
|
| 1808 |
+
-4.9660e-02,
|
| 1809 |
+
-1.2677e-01,
|
| 1810 |
+
3.4498e-02,
|
| 1811 |
+
2.7027e-02,
|
| 1812 |
+
9.1476e-02,
|
| 1813 |
+
-5.1170e-02,
|
| 1814 |
+
-3.4786e-02,
|
| 1815 |
+
-4.4356e-02,
|
| 1816 |
+
6.2440e-03,
|
| 1817 |
+
-3.5473e-02,
|
| 1818 |
+
-1.1076e-01,
|
| 1819 |
+
1.0014e-01,
|
| 1820 |
+
-1.5927e-02,
|
| 1821 |
+
-7.9539e-02,
|
| 1822 |
+
1.1542e-01,
|
| 1823 |
+
-3.6775e-03,
|
| 1824 |
+
2.5437e-02,
|
| 1825 |
+
2.1185e-02,
|
| 1826 |
+
1.0472e-01,
|
| 1827 |
+
-4.8937e-03,
|
| 1828 |
+
4.5876e-02,
|
| 1829 |
+
5.3122e-02,
|
| 1830 |
+
-1.9815e-02,
|
| 1831 |
+
-1.8126e-02,
|
| 1832 |
+
-2.3358e-02,
|
| 1833 |
+
1.2271e-01,
|
| 1834 |
+
9.8860e-02,
|
| 1835 |
+
4.5235e-02,
|
| 1836 |
+
6.2841e-02,
|
| 1837 |
+
1.6294e-01,
|
| 1838 |
+
-1.0909e-01,
|
| 1839 |
+
7.2012e-02,
|
| 1840 |
+
5.3389e-02,
|
| 1841 |
+
],
|
| 1842 |
+
[
|
| 1843 |
+
1.2605e-01,
|
| 1844 |
+
5.1723e-02,
|
| 1845 |
+
1.2152e-01,
|
| 1846 |
+
5.8291e-02,
|
| 1847 |
+
-3.8019e-02,
|
| 1848 |
+
8.8117e-02,
|
| 1849 |
+
-4.1927e-02,
|
| 1850 |
+
-2.3022e-02,
|
| 1851 |
+
-3.1158e-02,
|
| 1852 |
+
1.2518e-01,
|
| 1853 |
+
1.4279e-01,
|
| 1854 |
+
-7.1922e-02,
|
| 1855 |
+
1.0867e-01,
|
| 1856 |
+
3.3116e-02,
|
| 1857 |
+
-1.3669e-01,
|
| 1858 |
+
-3.2413e-02,
|
| 1859 |
+
9.0301e-02,
|
| 1860 |
+
5.9203e-02,
|
| 1861 |
+
-7.5021e-03,
|
| 1862 |
+
-6.9837e-02,
|
| 1863 |
+
-1.2463e-03,
|
| 1864 |
+
1.8891e-02,
|
| 1865 |
+
-1.1878e-01,
|
| 1866 |
+
6.1658e-02,
|
| 1867 |
+
-1.2649e-01,
|
| 1868 |
+
4.2450e-02,
|
| 1869 |
+
-1.6298e-01,
|
| 1870 |
+
1.5450e-01,
|
| 1871 |
+
-2.6732e-02,
|
| 1872 |
+
1.7891e-01,
|
| 1873 |
+
2.1083e-01,
|
| 1874 |
+
1.0432e-01,
|
| 1875 |
+
-1.3396e-01,
|
| 1876 |
+
6.9416e-02,
|
| 1877 |
+
-7.3193e-02,
|
| 1878 |
+
-6.8281e-02,
|
| 1879 |
+
9.9454e-02,
|
| 1880 |
+
-4.4528e-02,
|
| 1881 |
+
7.7992e-02,
|
| 1882 |
+
-2.6336e-03,
|
| 1883 |
+
6.9279e-02,
|
| 1884 |
+
-3.8836e-02,
|
| 1885 |
+
-2.8872e-02,
|
| 1886 |
+
5.6951e-02,
|
| 1887 |
+
8.7154e-02,
|
| 1888 |
+
6.1652e-02,
|
| 1889 |
+
-1.8049e-02,
|
| 1890 |
+
-1.2096e-01,
|
| 1891 |
+
1.3820e-01,
|
| 1892 |
+
5.1705e-02,
|
| 1893 |
+
3.4052e-02,
|
| 1894 |
+
1.1524e-01,
|
| 1895 |
+
-4.1216e-02,
|
| 1896 |
+
-8.5670e-02,
|
| 1897 |
+
7.1571e-02,
|
| 1898 |
+
-1.6001e-02,
|
| 1899 |
+
-8.8427e-02,
|
| 1900 |
+
3.1357e-02,
|
| 1901 |
+
-5.4897e-02,
|
| 1902 |
+
-3.1463e-02,
|
| 1903 |
+
-1.2070e-01,
|
| 1904 |
+
-5.7460e-02,
|
| 1905 |
+
-2.1424e-02,
|
| 1906 |
+
-1.2160e-01,
|
| 1907 |
+
1.0026e-01,
|
| 1908 |
+
4.7475e-02,
|
| 1909 |
+
-1.4578e-02,
|
| 1910 |
+
1.3247e-01,
|
| 1911 |
+
1.5272e-01,
|
| 1912 |
+
-2.9788e-02,
|
| 1913 |
+
8.2947e-02,
|
| 1914 |
+
7.9830e-02,
|
| 1915 |
+
-1.1615e-01,
|
| 1916 |
+
7.2949e-02,
|
| 1917 |
+
-1.2386e-01,
|
| 1918 |
+
-5.3969e-02,
|
| 1919 |
+
-1.3578e-01,
|
| 1920 |
+
4.0461e-02,
|
| 1921 |
+
1.2467e-01,
|
| 1922 |
+
-9.4575e-02,
|
| 1923 |
+
6.2182e-04,
|
| 1924 |
+
1.3108e-01,
|
| 1925 |
+
6.5035e-02,
|
| 1926 |
+
-5.7784e-02,
|
| 1927 |
+
4.2513e-02,
|
| 1928 |
+
-7.8118e-02,
|
| 1929 |
+
1.1274e-01,
|
| 1930 |
+
8.9333e-02,
|
| 1931 |
+
-4.9991e-02,
|
| 1932 |
+
7.4639e-02,
|
| 1933 |
+
3.0876e-01,
|
| 1934 |
+
7.3974e-02,
|
| 1935 |
+
-1.4039e-02,
|
| 1936 |
+
-7.4526e-02,
|
| 1937 |
+
6.5200e-02,
|
| 1938 |
+
-3.6421e-02,
|
| 1939 |
+
-1.6730e-01,
|
| 1940 |
+
4.1713e-02,
|
| 1941 |
+
-1.5316e-02,
|
| 1942 |
+
1.0056e-01,
|
| 1943 |
+
-5.0370e-02,
|
| 1944 |
+
-4.4531e-02,
|
| 1945 |
+
-5.0233e-02,
|
| 1946 |
+
3.2636e-02,
|
| 1947 |
+
-1.7609e-02,
|
| 1948 |
+
-1.1354e-01,
|
| 1949 |
+
8.1922e-02,
|
| 1950 |
+
-2.0907e-02,
|
| 1951 |
+
-1.3264e-02,
|
| 1952 |
+
1.5115e-01,
|
| 1953 |
+
1.2777e-02,
|
| 1954 |
+
3.8261e-02,
|
| 1955 |
+
2.1829e-02,
|
| 1956 |
+
5.5874e-02,
|
| 1957 |
+
6.8772e-03,
|
| 1958 |
+
-2.7772e-02,
|
| 1959 |
+
6.7979e-02,
|
| 1960 |
+
-3.9099e-02,
|
| 1961 |
+
-2.8619e-02,
|
| 1962 |
+
-5.6936e-02,
|
| 1963 |
+
1.3366e-01,
|
| 1964 |
+
9.4269e-02,
|
| 1965 |
+
4.4852e-02,
|
| 1966 |
+
7.6881e-02,
|
| 1967 |
+
9.6787e-02,
|
| 1968 |
+
-1.2885e-01,
|
| 1969 |
+
7.9722e-02,
|
| 1970 |
+
6.4991e-02,
|
| 1971 |
+
],
|
| 1972 |
+
[
|
| 1973 |
+
1.0575e-01,
|
| 1974 |
+
6.4565e-02,
|
| 1975 |
+
1.2479e-01,
|
| 1976 |
+
5.5616e-02,
|
| 1977 |
+
-5.5869e-02,
|
| 1978 |
+
8.9005e-02,
|
| 1979 |
+
-1.9612e-02,
|
| 1980 |
+
-3.3032e-02,
|
| 1981 |
+
-3.9719e-02,
|
| 1982 |
+
1.3884e-01,
|
| 1983 |
+
1.2010e-01,
|
| 1984 |
+
-6.3224e-02,
|
| 1985 |
+
1.0893e-01,
|
| 1986 |
+
4.4172e-02,
|
| 1987 |
+
-1.4283e-01,
|
| 1988 |
+
-3.8972e-02,
|
| 1989 |
+
1.1470e-01,
|
| 1990 |
+
7.7830e-02,
|
| 1991 |
+
-4.6450e-02,
|
| 1992 |
+
-8.7246e-02,
|
| 1993 |
+
-5.7215e-03,
|
| 1994 |
+
1.7476e-02,
|
| 1995 |
+
-9.0388e-02,
|
| 1996 |
+
7.4607e-02,
|
| 1997 |
+
-1.3105e-01,
|
| 1998 |
+
2.9371e-02,
|
| 1999 |
+
-1.2681e-01,
|
| 2000 |
+
1.6014e-01,
|
| 2001 |
+
-1.3655e-02,
|
| 2002 |
+
1.8492e-01,
|
| 2003 |
+
1.9841e-01,
|
| 2004 |
+
1.0942e-01,
|
| 2005 |
+
-1.1261e-01,
|
| 2006 |
+
6.8326e-02,
|
| 2007 |
+
-5.1130e-02,
|
| 2008 |
+
-7.1296e-02,
|
| 2009 |
+
9.3895e-02,
|
| 2010 |
+
-3.1097e-02,
|
| 2011 |
+
8.7043e-02,
|
| 2012 |
+
-1.2087e-02,
|
| 2013 |
+
7.3054e-02,
|
| 2014 |
+
-1.0602e-02,
|
| 2015 |
+
-3.6347e-02,
|
| 2016 |
+
3.1324e-02,
|
| 2017 |
+
7.5686e-02,
|
| 2018 |
+
5.3221e-02,
|
| 2019 |
+
-3.1793e-02,
|
| 2020 |
+
-1.3818e-01,
|
| 2021 |
+
1.4972e-01,
|
| 2022 |
+
9.0217e-02,
|
| 2023 |
+
2.6365e-02,
|
| 2024 |
+
1.1733e-01,
|
| 2025 |
+
-2.6107e-02,
|
| 2026 |
+
-1.1933e-01,
|
| 2027 |
+
6.5575e-02,
|
| 2028 |
+
-1.6907e-02,
|
| 2029 |
+
-1.0186e-01,
|
| 2030 |
+
3.3719e-02,
|
| 2031 |
+
-3.4021e-02,
|
| 2032 |
+
-1.0597e-02,
|
| 2033 |
+
-1.0478e-01,
|
| 2034 |
+
-3.4765e-02,
|
| 2035 |
+
-3.0666e-03,
|
| 2036 |
+
-1.2035e-01,
|
| 2037 |
+
1.1053e-01,
|
| 2038 |
+
5.2212e-02,
|
| 2039 |
+
-1.8638e-02,
|
| 2040 |
+
1.2226e-01,
|
| 2041 |
+
1.3614e-01,
|
| 2042 |
+
-4.3806e-02,
|
| 2043 |
+
4.7251e-02,
|
| 2044 |
+
9.2144e-02,
|
| 2045 |
+
-1.2505e-01,
|
| 2046 |
+
8.3020e-02,
|
| 2047 |
+
-1.1203e-01,
|
| 2048 |
+
-4.9654e-02,
|
| 2049 |
+
-1.1939e-01,
|
| 2050 |
+
4.4126e-02,
|
| 2051 |
+
1.1188e-01,
|
| 2052 |
+
-7.8910e-02,
|
| 2053 |
+
-4.1917e-03,
|
| 2054 |
+
1.3279e-01,
|
| 2055 |
+
5.0291e-02,
|
| 2056 |
+
-6.1770e-02,
|
| 2057 |
+
5.1914e-02,
|
| 2058 |
+
-6.8796e-02,
|
| 2059 |
+
1.2148e-01,
|
| 2060 |
+
7.6837e-02,
|
| 2061 |
+
-4.0098e-02,
|
| 2062 |
+
8.3547e-02,
|
| 2063 |
+
3.0367e-01,
|
| 2064 |
+
6.9357e-02,
|
| 2065 |
+
-2.5710e-02,
|
| 2066 |
+
-7.2644e-02,
|
| 2067 |
+
5.2612e-02,
|
| 2068 |
+
-5.3110e-02,
|
| 2069 |
+
-1.7360e-01,
|
| 2070 |
+
5.2791e-02,
|
| 2071 |
+
-1.6490e-02,
|
| 2072 |
+
9.9930e-02,
|
| 2073 |
+
-4.8174e-02,
|
| 2074 |
+
-3.0230e-02,
|
| 2075 |
+
-6.0898e-02,
|
| 2076 |
+
3.4064e-02,
|
| 2077 |
+
8.2446e-03,
|
| 2078 |
+
-1.0747e-01,
|
| 2079 |
+
6.9406e-02,
|
| 2080 |
+
-9.2400e-03,
|
| 2081 |
+
2.1804e-02,
|
| 2082 |
+
1.5491e-01,
|
| 2083 |
+
2.0964e-02,
|
| 2084 |
+
3.4691e-02,
|
| 2085 |
+
3.5648e-02,
|
| 2086 |
+
4.4363e-02,
|
| 2087 |
+
-3.2605e-03,
|
| 2088 |
+
-5.9988e-02,
|
| 2089 |
+
9.3354e-02,
|
| 2090 |
+
-7.4183e-02,
|
| 2091 |
+
-3.5824e-02,
|
| 2092 |
+
-7.1163e-02,
|
| 2093 |
+
1.4776e-01,
|
| 2094 |
+
1.0179e-01,
|
| 2095 |
+
4.1685e-02,
|
| 2096 |
+
6.7698e-02,
|
| 2097 |
+
8.4053e-02,
|
| 2098 |
+
-1.4797e-01,
|
| 2099 |
+
9.9115e-02,
|
| 2100 |
+
7.2061e-02,
|
| 2101 |
+
],
|
| 2102 |
+
[
|
| 2103 |
+
8.3987e-02,
|
| 2104 |
+
6.9951e-02,
|
| 2105 |
+
1.3728e-01,
|
| 2106 |
+
6.4616e-02,
|
| 2107 |
+
-5.5591e-02,
|
| 2108 |
+
8.8007e-02,
|
| 2109 |
+
-1.7926e-02,
|
| 2110 |
+
-4.8462e-02,
|
| 2111 |
+
-4.8522e-02,
|
| 2112 |
+
1.5932e-01,
|
| 2113 |
+
1.0766e-01,
|
| 2114 |
+
-4.9589e-02,
|
| 2115 |
+
1.0511e-01,
|
| 2116 |
+
4.4010e-02,
|
| 2117 |
+
-1.3653e-01,
|
| 2118 |
+
-4.1380e-02,
|
| 2119 |
+
1.3629e-01,
|
| 2120 |
+
9.2007e-02,
|
| 2121 |
+
-5.2961e-02,
|
| 2122 |
+
-7.1865e-02,
|
| 2123 |
+
-2.8329e-03,
|
| 2124 |
+
1.3417e-02,
|
| 2125 |
+
-5.2565e-02,
|
| 2126 |
+
6.2258e-02,
|
| 2127 |
+
-1.2135e-01,
|
| 2128 |
+
2.7531e-02,
|
| 2129 |
+
-9.4902e-02,
|
| 2130 |
+
1.6567e-01,
|
| 2131 |
+
-1.6613e-02,
|
| 2132 |
+
1.8443e-01,
|
| 2133 |
+
1.6290e-01,
|
| 2134 |
+
1.1109e-01,
|
| 2135 |
+
-1.1476e-01,
|
| 2136 |
+
6.5613e-02,
|
| 2137 |
+
-1.7283e-02,
|
| 2138 |
+
-8.7120e-02,
|
| 2139 |
+
1.0862e-01,
|
| 2140 |
+
-2.5325e-02,
|
| 2141 |
+
8.9025e-02,
|
| 2142 |
+
-1.8290e-02,
|
| 2143 |
+
7.2979e-02,
|
| 2144 |
+
1.1878e-04,
|
| 2145 |
+
-4.1007e-02,
|
| 2146 |
+
1.9679e-02,
|
| 2147 |
+
6.1887e-02,
|
| 2148 |
+
4.0949e-02,
|
| 2149 |
+
-3.6016e-02,
|
| 2150 |
+
-1.5569e-01,
|
| 2151 |
+
1.4839e-01,
|
| 2152 |
+
1.1372e-01,
|
| 2153 |
+
1.8360e-02,
|
| 2154 |
+
9.3030e-02,
|
| 2155 |
+
-1.8070e-02,
|
| 2156 |
+
-1.5578e-01,
|
| 2157 |
+
6.1180e-02,
|
| 2158 |
+
-1.9569e-02,
|
| 2159 |
+
-1.1221e-01,
|
| 2160 |
+
4.0037e-02,
|
| 2161 |
+
-2.3712e-02,
|
| 2162 |
+
-1.0311e-02,
|
| 2163 |
+
-1.0530e-01,
|
| 2164 |
+
-1.2916e-02,
|
| 2165 |
+
3.1546e-02,
|
| 2166 |
+
-1.1647e-01,
|
| 2167 |
+
1.2109e-01,
|
| 2168 |
+
5.8714e-02,
|
| 2169 |
+
-1.9454e-02,
|
| 2170 |
+
9.9438e-02,
|
| 2171 |
+
1.1088e-01,
|
| 2172 |
+
-7.4443e-02,
|
| 2173 |
+
1.6456e-02,
|
| 2174 |
+
8.7619e-02,
|
| 2175 |
+
-1.1460e-01,
|
| 2176 |
+
9.7142e-02,
|
| 2177 |
+
-1.1083e-01,
|
| 2178 |
+
-5.2367e-02,
|
| 2179 |
+
-1.2157e-01,
|
| 2180 |
+
4.6784e-02,
|
| 2181 |
+
8.5968e-02,
|
| 2182 |
+
-7.2488e-02,
|
| 2183 |
+
-1.2658e-02,
|
| 2184 |
+
1.4136e-01,
|
| 2185 |
+
1.7934e-02,
|
| 2186 |
+
-6.4075e-02,
|
| 2187 |
+
5.3809e-02,
|
| 2188 |
+
-5.8649e-02,
|
| 2189 |
+
1.2410e-01,
|
| 2190 |
+
6.7307e-02,
|
| 2191 |
+
-5.3157e-02,
|
| 2192 |
+
8.5616e-02,
|
| 2193 |
+
2.8266e-01,
|
| 2194 |
+
6.4775e-02,
|
| 2195 |
+
-2.9330e-02,
|
| 2196 |
+
-8.7733e-02,
|
| 2197 |
+
1.3974e-02,
|
| 2198 |
+
-7.9092e-02,
|
| 2199 |
+
-1.6691e-01,
|
| 2200 |
+
5.9037e-02,
|
| 2201 |
+
4.1784e-03,
|
| 2202 |
+
9.8219e-02,
|
| 2203 |
+
-3.6970e-02,
|
| 2204 |
+
8.6754e-03,
|
| 2205 |
+
-5.5234e-02,
|
| 2206 |
+
3.4627e-02,
|
| 2207 |
+
3.5126e-02,
|
| 2208 |
+
-9.5508e-02,
|
| 2209 |
+
6.4539e-02,
|
| 2210 |
+
-9.1506e-04,
|
| 2211 |
+
2.9144e-02,
|
| 2212 |
+
1.3975e-01,
|
| 2213 |
+
1.5472e-02,
|
| 2214 |
+
3.9015e-02,
|
| 2215 |
+
4.6270e-02,
|
| 2216 |
+
5.4053e-02,
|
| 2217 |
+
-1.2525e-02,
|
| 2218 |
+
-6.6168e-02,
|
| 2219 |
+
1.2463e-01,
|
| 2220 |
+
-1.0793e-01,
|
| 2221 |
+
-4.0659e-02,
|
| 2222 |
+
-8.1224e-02,
|
| 2223 |
+
1.5702e-01,
|
| 2224 |
+
1.2323e-01,
|
| 2225 |
+
3.3473e-02,
|
| 2226 |
+
6.1162e-02,
|
| 2227 |
+
8.3375e-02,
|
| 2228 |
+
-1.7863e-01,
|
| 2229 |
+
1.1536e-01,
|
| 2230 |
+
6.9906e-02,
|
| 2231 |
+
],
|
| 2232 |
+
[
|
| 2233 |
+
6.2508e-02,
|
| 2234 |
+
8.5713e-02,
|
| 2235 |
+
1.3566e-01,
|
| 2236 |
+
8.5148e-02,
|
| 2237 |
+
-2.2642e-02,
|
| 2238 |
+
5.8889e-02,
|
| 2239 |
+
-3.3654e-02,
|
| 2240 |
+
-6.6948e-02,
|
| 2241 |
+
-5.1541e-02,
|
| 2242 |
+
1.7082e-01,
|
| 2243 |
+
1.1639e-01,
|
| 2244 |
+
-3.9750e-02,
|
| 2245 |
+
8.5338e-02,
|
| 2246 |
+
2.8182e-02,
|
| 2247 |
+
-1.1108e-01,
|
| 2248 |
+
-3.5316e-02,
|
| 2249 |
+
1.4888e-01,
|
| 2250 |
+
1.0210e-01,
|
| 2251 |
+
-3.4537e-02,
|
| 2252 |
+
-1.1950e-02,
|
| 2253 |
+
5.0482e-03,
|
| 2254 |
+
1.8051e-02,
|
| 2255 |
+
-2.2067e-02,
|
| 2256 |
+
1.8682e-02,
|
| 2257 |
+
-9.7924e-02,
|
| 2258 |
+
2.6326e-02,
|
| 2259 |
+
-7.6128e-02,
|
| 2260 |
+
1.7675e-01,
|
| 2261 |
+
-1.6092e-02,
|
| 2262 |
+
1.6355e-01,
|
| 2263 |
+
1.1133e-01,
|
| 2264 |
+
1.1036e-01,
|
| 2265 |
+
-1.4070e-01,
|
| 2266 |
+
6.9723e-02,
|
| 2267 |
+
2.0482e-02,
|
| 2268 |
+
-1.0421e-01,
|
| 2269 |
+
1.2920e-01,
|
| 2270 |
+
-3.1272e-02,
|
| 2271 |
+
7.6070e-02,
|
| 2272 |
+
-3.1384e-02,
|
| 2273 |
+
6.7374e-02,
|
| 2274 |
+
-8.3764e-05,
|
| 2275 |
+
-2.1820e-02,
|
| 2276 |
+
1.4192e-02,
|
| 2277 |
+
2.3975e-02,
|
| 2278 |
+
2.3384e-02,
|
| 2279 |
+
-2.3589e-02,
|
| 2280 |
+
-1.7196e-01,
|
| 2281 |
+
1.4986e-01,
|
| 2282 |
+
1.1465e-01,
|
| 2283 |
+
2.0120e-02,
|
| 2284 |
+
4.8034e-02,
|
| 2285 |
+
-3.9982e-02,
|
| 2286 |
+
-1.8704e-01,
|
| 2287 |
+
6.2222e-02,
|
| 2288 |
+
-1.4799e-02,
|
| 2289 |
+
-1.0783e-01,
|
| 2290 |
+
5.4098e-02,
|
| 2291 |
+
-1.2046e-02,
|
| 2292 |
+
-1.5444e-02,
|
| 2293 |
+
-1.4001e-01,
|
| 2294 |
+
1.5944e-02,
|
| 2295 |
+
7.9476e-02,
|
| 2296 |
+
-9.7107e-02,
|
| 2297 |
+
1.0629e-01,
|
| 2298 |
+
7.1731e-02,
|
| 2299 |
+
-8.1614e-03,
|
| 2300 |
+
6.2800e-02,
|
| 2301 |
+
5.5151e-02,
|
| 2302 |
+
-1.0514e-01,
|
| 2303 |
+
1.7916e-02,
|
| 2304 |
+
8.1229e-02,
|
| 2305 |
+
-7.8761e-02,
|
| 2306 |
+
1.1222e-01,
|
| 2307 |
+
-1.1032e-01,
|
| 2308 |
+
-4.8039e-02,
|
| 2309 |
+
-1.5340e-01,
|
| 2310 |
+
6.0481e-02,
|
| 2311 |
+
3.2276e-02,
|
| 2312 |
+
-6.2797e-02,
|
| 2313 |
+
-3.3934e-02,
|
| 2314 |
+
1.3062e-01,
|
| 2315 |
+
-6.3068e-03,
|
| 2316 |
+
-6.5936e-02,
|
| 2317 |
+
4.2361e-02,
|
| 2318 |
+
-4.6102e-02,
|
| 2319 |
+
1.2669e-01,
|
| 2320 |
+
6.1909e-02,
|
| 2321 |
+
-5.7771e-02,
|
| 2322 |
+
7.8385e-02,
|
| 2323 |
+
2.4836e-01,
|
| 2324 |
+
7.5433e-02,
|
| 2325 |
+
-2.0151e-02,
|
| 2326 |
+
-1.2117e-01,
|
| 2327 |
+
-4.1874e-02,
|
| 2328 |
+
-1.1751e-01,
|
| 2329 |
+
-1.4471e-01,
|
| 2330 |
+
6.3096e-02,
|
| 2331 |
+
2.9419e-02,
|
| 2332 |
+
1.0021e-01,
|
| 2333 |
+
-1.2180e-02,
|
| 2334 |
+
5.0896e-02,
|
| 2335 |
+
-4.0094e-02,
|
| 2336 |
+
4.1059e-02,
|
| 2337 |
+
8.0853e-02,
|
| 2338 |
+
-7.4614e-02,
|
| 2339 |
+
7.5243e-02,
|
| 2340 |
+
1.4928e-02,
|
| 2341 |
+
1.1477e-02,
|
| 2342 |
+
1.2385e-01,
|
| 2343 |
+
-1.4719e-02,
|
| 2344 |
+
5.3751e-02,
|
| 2345 |
+
5.2591e-02,
|
| 2346 |
+
7.2013e-02,
|
| 2347 |
+
-1.6333e-02,
|
| 2348 |
+
-5.0256e-02,
|
| 2349 |
+
1.4199e-01,
|
| 2350 |
+
-1.3433e-01,
|
| 2351 |
+
-7.1574e-02,
|
| 2352 |
+
-7.4449e-02,
|
| 2353 |
+
1.6136e-01,
|
| 2354 |
+
1.5659e-01,
|
| 2355 |
+
2.1466e-02,
|
| 2356 |
+
6.9775e-02,
|
| 2357 |
+
1.0352e-01,
|
| 2358 |
+
-1.9641e-01,
|
| 2359 |
+
1.3156e-01,
|
| 2360 |
+
5.5903e-02,
|
| 2361 |
+
],
|
| 2362 |
+
[
|
| 2363 |
+
4.4988e-02,
|
| 2364 |
+
1.0390e-01,
|
| 2365 |
+
1.1266e-01,
|
| 2366 |
+
1.1661e-01,
|
| 2367 |
+
2.1212e-02,
|
| 2368 |
+
1.4641e-02,
|
| 2369 |
+
-3.1484e-02,
|
| 2370 |
+
-8.3443e-02,
|
| 2371 |
+
-4.4991e-02,
|
| 2372 |
+
1.5687e-01,
|
| 2373 |
+
1.3158e-01,
|
| 2374 |
+
-3.3434e-02,
|
| 2375 |
+
6.5104e-02,
|
| 2376 |
+
2.0808e-02,
|
| 2377 |
+
-7.0680e-02,
|
| 2378 |
+
-4.2508e-02,
|
| 2379 |
+
1.4304e-01,
|
| 2380 |
+
9.8483e-02,
|
| 2381 |
+
-2.6904e-02,
|
| 2382 |
+
3.2902e-02,
|
| 2383 |
+
1.1152e-02,
|
| 2384 |
+
2.1118e-02,
|
| 2385 |
+
-1.4842e-02,
|
| 2386 |
+
-2.2356e-02,
|
| 2387 |
+
-8.6942e-02,
|
| 2388 |
+
2.6609e-02,
|
| 2389 |
+
-6.2533e-02,
|
| 2390 |
+
1.7495e-01,
|
| 2391 |
+
-1.0246e-02,
|
| 2392 |
+
1.2697e-01,
|
| 2393 |
+
7.9345e-02,
|
| 2394 |
+
1.0189e-01,
|
| 2395 |
+
-1.7178e-01,
|
| 2396 |
+
7.5006e-02,
|
| 2397 |
+
4.5051e-02,
|
| 2398 |
+
-1.0753e-01,
|
| 2399 |
+
1.2829e-01,
|
| 2400 |
+
-3.3422e-02,
|
| 2401 |
+
7.8522e-02,
|
| 2402 |
+
-4.5604e-02,
|
| 2403 |
+
5.2822e-02,
|
| 2404 |
+
8.3934e-03,
|
| 2405 |
+
-1.4676e-02,
|
| 2406 |
+
1.0482e-02,
|
| 2407 |
+
-6.9389e-03,
|
| 2408 |
+
2.2131e-03,
|
| 2409 |
+
-2.0089e-02,
|
| 2410 |
+
-1.7261e-01,
|
| 2411 |
+
1.5468e-01,
|
| 2412 |
+
1.1537e-01,
|
| 2413 |
+
2.7489e-02,
|
| 2414 |
+
2.9948e-02,
|
| 2415 |
+
-7.4234e-02,
|
| 2416 |
+
-1.9946e-01,
|
| 2417 |
+
7.4632e-02,
|
| 2418 |
+
2.2249e-03,
|
| 2419 |
+
-9.7061e-02,
|
| 2420 |
+
6.4988e-02,
|
| 2421 |
+
-1.1239e-02,
|
| 2422 |
+
-2.6152e-02,
|
| 2423 |
+
-1.6496e-01,
|
| 2424 |
+
3.0305e-02,
|
| 2425 |
+
1.0491e-01,
|
| 2426 |
+
-6.7692e-02,
|
| 2427 |
+
7.3323e-02,
|
| 2428 |
+
7.0258e-02,
|
| 2429 |
+
1.2020e-02,
|
| 2430 |
+
4.1457e-02,
|
| 2431 |
+
3.7126e-03,
|
| 2432 |
+
-1.0465e-01,
|
| 2433 |
+
2.7035e-02,
|
| 2434 |
+
8.1376e-02,
|
| 2435 |
+
-4.0890e-02,
|
| 2436 |
+
1.0791e-01,
|
| 2437 |
+
-1.2141e-01,
|
| 2438 |
+
-1.6070e-02,
|
| 2439 |
+
-1.7111e-01,
|
| 2440 |
+
7.4218e-02,
|
| 2441 |
+
-2.4698e-02,
|
| 2442 |
+
-3.7496e-02,
|
| 2443 |
+
-4.5666e-02,
|
| 2444 |
+
1.0478e-01,
|
| 2445 |
+
-1.7289e-03,
|
| 2446 |
+
-7.1823e-02,
|
| 2447 |
+
2.7480e-02,
|
| 2448 |
+
-5.5305e-02,
|
| 2449 |
+
1.2323e-01,
|
| 2450 |
+
5.3008e-02,
|
| 2451 |
+
-5.6903e-02,
|
| 2452 |
+
6.6087e-02,
|
| 2453 |
+
2.1523e-01,
|
| 2454 |
+
8.2657e-02,
|
| 2455 |
+
-9.3275e-03,
|
| 2456 |
+
-1.3791e-01,
|
| 2457 |
+
-6.7856e-02,
|
| 2458 |
+
-1.4959e-01,
|
| 2459 |
+
-1.1916e-01,
|
| 2460 |
+
6.2014e-02,
|
| 2461 |
+
3.8735e-02,
|
| 2462 |
+
9.7171e-02,
|
| 2463 |
+
2.6820e-02,
|
| 2464 |
+
7.4336e-02,
|
| 2465 |
+
-2.9922e-02,
|
| 2466 |
+
5.3645e-02,
|
| 2467 |
+
1.0981e-01,
|
| 2468 |
+
-3.7215e-02,
|
| 2469 |
+
9.4254e-02,
|
| 2470 |
+
4.2902e-02,
|
| 2471 |
+
-2.0969e-03,
|
| 2472 |
+
1.1838e-01,
|
| 2473 |
+
-5.4015e-02,
|
| 2474 |
+
5.3799e-02,
|
| 2475 |
+
4.8568e-02,
|
| 2476 |
+
8.0494e-02,
|
| 2477 |
+
-2.1410e-02,
|
| 2478 |
+
-2.0629e-02,
|
| 2479 |
+
1.3477e-01,
|
| 2480 |
+
-1.4177e-01,
|
| 2481 |
+
-1.1144e-01,
|
| 2482 |
+
-5.1781e-02,
|
| 2483 |
+
1.5780e-01,
|
| 2484 |
+
1.9357e-01,
|
| 2485 |
+
2.5627e-02,
|
| 2486 |
+
7.5402e-02,
|
| 2487 |
+
1.1982e-01,
|
| 2488 |
+
-1.8961e-01,
|
| 2489 |
+
1.4646e-01,
|
| 2490 |
+
4.2665e-02,
|
| 2491 |
+
],
|
| 2492 |
+
[
|
| 2493 |
+
5.1689e-02,
|
| 2494 |
+
1.0737e-01,
|
| 2495 |
+
1.1035e-01,
|
| 2496 |
+
1.1308e-01,
|
| 2497 |
+
2.0363e-02,
|
| 2498 |
+
1.9703e-02,
|
| 2499 |
+
-3.2107e-02,
|
| 2500 |
+
-9.0838e-02,
|
| 2501 |
+
-3.7066e-02,
|
| 2502 |
+
1.5839e-01,
|
| 2503 |
+
1.3202e-01,
|
| 2504 |
+
-3.9661e-02,
|
| 2505 |
+
6.3263e-02,
|
| 2506 |
+
1.4509e-02,
|
| 2507 |
+
-6.0145e-02,
|
| 2508 |
+
-4.1459e-02,
|
| 2509 |
+
1.4670e-01,
|
| 2510 |
+
9.4701e-02,
|
| 2511 |
+
-2.7710e-02,
|
| 2512 |
+
3.4281e-02,
|
| 2513 |
+
1.2373e-02,
|
| 2514 |
+
2.0087e-02,
|
| 2515 |
+
-2.0821e-02,
|
| 2516 |
+
-1.6274e-02,
|
| 2517 |
+
-7.9908e-02,
|
| 2518 |
+
2.6209e-02,
|
| 2519 |
+
-7.0731e-02,
|
| 2520 |
+
1.7365e-01,
|
| 2521 |
+
-8.5357e-03,
|
| 2522 |
+
1.2784e-01,
|
| 2523 |
+
7.9591e-02,
|
| 2524 |
+
9.7291e-02,
|
| 2525 |
+
-1.6958e-01,
|
| 2526 |
+
7.5774e-02,
|
| 2527 |
+
4.4993e-02,
|
| 2528 |
+
-1.0499e-01,
|
| 2529 |
+
1.2133e-01,
|
| 2530 |
+
-4.2564e-02,
|
| 2531 |
+
7.7296e-02,
|
| 2532 |
+
-3.9049e-02,
|
| 2533 |
+
5.4639e-02,
|
| 2534 |
+
3.7831e-03,
|
| 2535 |
+
-1.2108e-02,
|
| 2536 |
+
1.7782e-02,
|
| 2537 |
+
-1.8517e-03,
|
| 2538 |
+
1.1160e-02,
|
| 2539 |
+
-1.9819e-02,
|
| 2540 |
+
-1.7390e-01,
|
| 2541 |
+
1.5853e-01,
|
| 2542 |
+
1.1225e-01,
|
| 2543 |
+
2.6839e-02,
|
| 2544 |
+
3.1746e-02,
|
| 2545 |
+
-8.1013e-02,
|
| 2546 |
+
-1.9950e-01,
|
| 2547 |
+
7.7933e-02,
|
| 2548 |
+
4.3883e-03,
|
| 2549 |
+
-9.1775e-02,
|
| 2550 |
+
6.3761e-02,
|
| 2551 |
+
-2.0220e-02,
|
| 2552 |
+
-2.0873e-02,
|
| 2553 |
+
-1.6981e-01,
|
| 2554 |
+
3.2587e-02,
|
| 2555 |
+
1.0188e-01,
|
| 2556 |
+
-7.2338e-02,
|
| 2557 |
+
7.9739e-02,
|
| 2558 |
+
7.2336e-02,
|
| 2559 |
+
1.2712e-02,
|
| 2560 |
+
4.6304e-02,
|
| 2561 |
+
1.1977e-02,
|
| 2562 |
+
-9.9069e-02,
|
| 2563 |
+
3.2361e-02,
|
| 2564 |
+
7.4647e-02,
|
| 2565 |
+
-3.2075e-02,
|
| 2566 |
+
1.0834e-01,
|
| 2567 |
+
-1.2421e-01,
|
| 2568 |
+
-1.4408e-02,
|
| 2569 |
+
-1.7591e-01,
|
| 2570 |
+
7.6520e-02,
|
| 2571 |
+
-2.1893e-02,
|
| 2572 |
+
-4.0591e-02,
|
| 2573 |
+
-3.9790e-02,
|
| 2574 |
+
1.0072e-01,
|
| 2575 |
+
2.1907e-03,
|
| 2576 |
+
-7.5756e-02,
|
| 2577 |
+
3.4002e-02,
|
| 2578 |
+
-6.2571e-02,
|
| 2579 |
+
1.2714e-01,
|
| 2580 |
+
5.2011e-02,
|
| 2581 |
+
-5.6154e-02,
|
| 2582 |
+
6.2876e-02,
|
| 2583 |
+
2.0992e-01,
|
| 2584 |
+
8.9547e-02,
|
| 2585 |
+
-1.2875e-02,
|
| 2586 |
+
-1.3528e-01,
|
| 2587 |
+
-6.6275e-02,
|
| 2588 |
+
-1.4322e-01,
|
| 2589 |
+
-1.0560e-01,
|
| 2590 |
+
5.9555e-02,
|
| 2591 |
+
4.4426e-02,
|
| 2592 |
+
1.0047e-01,
|
| 2593 |
+
3.3182e-02,
|
| 2594 |
+
7.2001e-02,
|
| 2595 |
+
-3.6514e-02,
|
| 2596 |
+
5.0708e-02,
|
| 2597 |
+
1.0564e-01,
|
| 2598 |
+
-4.1174e-02,
|
| 2599 |
+
1.0378e-01,
|
| 2600 |
+
4.2651e-02,
|
| 2601 |
+
-2.6353e-03,
|
| 2602 |
+
1.1964e-01,
|
| 2603 |
+
-6.2808e-02,
|
| 2604 |
+
5.9555e-02,
|
| 2605 |
+
5.4234e-02,
|
| 2606 |
+
8.3802e-02,
|
| 2607 |
+
-1.2534e-02,
|
| 2608 |
+
-1.7949e-02,
|
| 2609 |
+
1.3403e-01,
|
| 2610 |
+
-1.3682e-01,
|
| 2611 |
+
-1.1048e-01,
|
| 2612 |
+
-5.1154e-02,
|
| 2613 |
+
1.5967e-01,
|
| 2614 |
+
1.9743e-01,
|
| 2615 |
+
3.2240e-02,
|
| 2616 |
+
7.4049e-02,
|
| 2617 |
+
1.2060e-01,
|
| 2618 |
+
-1.9087e-01,
|
| 2619 |
+
1.3942e-01,
|
| 2620 |
+
4.1168e-02,
|
| 2621 |
+
],
|
| 2622 |
+
[
|
| 2623 |
+
7.2669e-02,
|
| 2624 |
+
1.0343e-01,
|
| 2625 |
+
1.1966e-01,
|
| 2626 |
+
9.3777e-02,
|
| 2627 |
+
-4.3358e-03,
|
| 2628 |
+
5.0720e-02,
|
| 2629 |
+
-3.8923e-02,
|
| 2630 |
+
-9.1626e-02,
|
| 2631 |
+
-3.0056e-02,
|
| 2632 |
+
1.6863e-01,
|
| 2633 |
+
1.2676e-01,
|
| 2634 |
+
-5.3184e-02,
|
| 2635 |
+
7.4056e-02,
|
| 2636 |
+
1.5517e-02,
|
| 2637 |
+
-7.5657e-02,
|
| 2638 |
+
-3.7712e-02,
|
| 2639 |
+
1.5280e-01,
|
| 2640 |
+
9.0719e-02,
|
| 2641 |
+
-3.1311e-02,
|
| 2642 |
+
1.7038e-02,
|
| 2643 |
+
1.0062e-02,
|
| 2644 |
+
1.4759e-02,
|
| 2645 |
+
-3.4438e-02,
|
| 2646 |
+
1.5206e-02,
|
| 2647 |
+
-7.7897e-02,
|
| 2648 |
+
2.7431e-02,
|
| 2649 |
+
-9.0602e-02,
|
| 2650 |
+
1.7164e-01,
|
| 2651 |
+
-9.9721e-03,
|
| 2652 |
+
1.4776e-01,
|
| 2653 |
+
1.0475e-01,
|
| 2654 |
+
9.0160e-02,
|
| 2655 |
+
-1.5270e-01,
|
| 2656 |
+
7.4838e-02,
|
| 2657 |
+
2.4463e-02,
|
| 2658 |
+
-1.0180e-01,
|
| 2659 |
+
1.1501e-01,
|
| 2660 |
+
-5.0178e-02,
|
| 2661 |
+
7.2532e-02,
|
| 2662 |
+
-1.8656e-02,
|
| 2663 |
+
6.9202e-02,
|
| 2664 |
+
-9.6694e-03,
|
| 2665 |
+
-1.8219e-02,
|
| 2666 |
+
3.5159e-02,
|
| 2667 |
+
2.5262e-02,
|
| 2668 |
+
3.4003e-02,
|
| 2669 |
+
-1.4053e-02,
|
| 2670 |
+
-1.7146e-01,
|
| 2671 |
+
1.6299e-01,
|
| 2672 |
+
1.0628e-01,
|
| 2673 |
+
2.3901e-02,
|
| 2674 |
+
4.2174e-02,
|
| 2675 |
+
-7.0690e-02,
|
| 2676 |
+
-1.8996e-01,
|
| 2677 |
+
7.4249e-02,
|
| 2678 |
+
-2.3634e-03,
|
| 2679 |
+
-8.9371e-02,
|
| 2680 |
+
5.7919e-02,
|
| 2681 |
+
-3.2949e-02,
|
| 2682 |
+
-2.4951e-03,
|
| 2683 |
+
-1.6144e-01,
|
| 2684 |
+
3.1264e-02,
|
| 2685 |
+
8.4885e-02,
|
| 2686 |
+
-9.7903e-02,
|
| 2687 |
+
1.0806e-01,
|
| 2688 |
+
7.3583e-02,
|
| 2689 |
+
1.4389e-03,
|
| 2690 |
+
6.4343e-02,
|
| 2691 |
+
5.4305e-02,
|
| 2692 |
+
-9.2823e-02,
|
| 2693 |
+
3.4699e-02,
|
| 2694 |
+
6.5887e-02,
|
| 2695 |
+
-4.1142e-02,
|
| 2696 |
+
1.1057e-01,
|
| 2697 |
+
-1.2077e-01,
|
| 2698 |
+
-3.4178e-02,
|
| 2699 |
+
-1.7040e-01,
|
| 2700 |
+
7.2546e-02,
|
| 2701 |
+
1.9399e-02,
|
| 2702 |
+
-6.3051e-02,
|
| 2703 |
+
-3.0156e-02,
|
| 2704 |
+
1.1501e-01,
|
| 2705 |
+
3.9456e-03,
|
| 2706 |
+
-7.8346e-02,
|
| 2707 |
+
5.0548e-02,
|
| 2708 |
+
-6.3681e-02,
|
| 2709 |
+
1.3261e-01,
|
| 2710 |
+
6.1531e-02,
|
| 2711 |
+
-5.1743e-02,
|
| 2712 |
+
6.4762e-02,
|
| 2713 |
+
2.3264e-01,
|
| 2714 |
+
9.4896e-02,
|
| 2715 |
+
-2.0536e-02,
|
| 2716 |
+
-1.1807e-01,
|
| 2717 |
+
-4.9545e-02,
|
| 2718 |
+
-1.1460e-01,
|
| 2719 |
+
-1.0079e-01,
|
| 2720 |
+
5.7836e-02,
|
| 2721 |
+
4.4144e-02,
|
| 2722 |
+
1.1039e-01,
|
| 2723 |
+
2.1311e-02,
|
| 2724 |
+
4.8694e-02,
|
| 2725 |
+
-4.7126e-02,
|
| 2726 |
+
3.7200e-02,
|
| 2727 |
+
8.3108e-02,
|
| 2728 |
+
-7.0069e-02,
|
| 2729 |
+
9.7451e-02,
|
| 2730 |
+
2.0983e-02,
|
| 2731 |
+
-4.1628e-04,
|
| 2732 |
+
1.2463e-01,
|
| 2733 |
+
-5.0752e-02,
|
| 2734 |
+
7.0680e-02,
|
| 2735 |
+
6.3588e-02,
|
| 2736 |
+
8.6767e-02,
|
| 2737 |
+
6.3361e-04,
|
| 2738 |
+
-2.5236e-02,
|
| 2739 |
+
1.3658e-01,
|
| 2740 |
+
-1.1925e-01,
|
| 2741 |
+
-8.3861e-02,
|
| 2742 |
+
-6.3728e-02,
|
| 2743 |
+
1.6767e-01,
|
| 2744 |
+
1.7967e-01,
|
| 2745 |
+
3.3894e-02,
|
| 2746 |
+
7.2830e-02,
|
| 2747 |
+
1.1590e-01,
|
| 2748 |
+
-1.9359e-01,
|
| 2749 |
+
1.2254e-01,
|
| 2750 |
+
4.7767e-02,
|
| 2751 |
+
],
|
| 2752 |
+
[
|
| 2753 |
+
8.4189e-02,
|
| 2754 |
+
9.3299e-02,
|
| 2755 |
+
1.1532e-01,
|
| 2756 |
+
8.4670e-02,
|
| 2757 |
+
-9.7533e-03,
|
| 2758 |
+
6.4423e-02,
|
| 2759 |
+
-4.3742e-02,
|
| 2760 |
+
-9.0334e-02,
|
| 2761 |
+
-1.9307e-02,
|
| 2762 |
+
1.7434e-01,
|
| 2763 |
+
1.2522e-01,
|
| 2764 |
+
-6.4064e-02,
|
| 2765 |
+
7.7841e-02,
|
| 2766 |
+
2.5594e-02,
|
| 2767 |
+
-9.4764e-02,
|
| 2768 |
+
-3.8088e-02,
|
| 2769 |
+
1.5148e-01,
|
| 2770 |
+
8.7002e-02,
|
| 2771 |
+
-3.8634e-02,
|
| 2772 |
+
1.6073e-02,
|
| 2773 |
+
1.0152e-02,
|
| 2774 |
+
8.9035e-03,
|
| 2775 |
+
-3.9583e-02,
|
| 2776 |
+
3.3614e-02,
|
| 2777 |
+
-7.4457e-02,
|
| 2778 |
+
2.6379e-02,
|
| 2779 |
+
-9.8885e-02,
|
| 2780 |
+
1.6510e-01,
|
| 2781 |
+
-1.1651e-02,
|
| 2782 |
+
1.5700e-01,
|
| 2783 |
+
1.3055e-01,
|
| 2784 |
+
7.7680e-02,
|
| 2785 |
+
-1.3690e-01,
|
| 2786 |
+
7.0143e-02,
|
| 2787 |
+
5.4565e-03,
|
| 2788 |
+
-1.0524e-01,
|
| 2789 |
+
1.1096e-01,
|
| 2790 |
+
-4.6091e-02,
|
| 2791 |
+
6.8167e-02,
|
| 2792 |
+
-5.6453e-03,
|
| 2793 |
+
7.2094e-02,
|
| 2794 |
+
-1.8229e-02,
|
| 2795 |
+
-2.5539e-02,
|
| 2796 |
+
3.9328e-02,
|
| 2797 |
+
4.3699e-02,
|
| 2798 |
+
4.4686e-02,
|
| 2799 |
+
-1.2072e-02,
|
| 2800 |
+
-1.6738e-01,
|
| 2801 |
+
1.6301e-01,
|
| 2802 |
+
1.0474e-01,
|
| 2803 |
+
1.4918e-02,
|
| 2804 |
+
5.4164e-02,
|
| 2805 |
+
-7.2489e-02,
|
| 2806 |
+
-1.7993e-01,
|
| 2807 |
+
7.7292e-02,
|
| 2808 |
+
-2.8187e-03,
|
| 2809 |
+
-8.9506e-02,
|
| 2810 |
+
5.6049e-02,
|
| 2811 |
+
-3.1474e-02,
|
| 2812 |
+
4.7455e-03,
|
| 2813 |
+
-1.5338e-01,
|
| 2814 |
+
2.2827e-02,
|
| 2815 |
+
6.7546e-02,
|
| 2816 |
+
-1.1578e-01,
|
| 2817 |
+
1.2026e-01,
|
| 2818 |
+
8.2049e-02,
|
| 2819 |
+
-1.1262e-02,
|
| 2820 |
+
7.4682e-02,
|
| 2821 |
+
7.3023e-02,
|
| 2822 |
+
-8.6490e-02,
|
| 2823 |
+
3.1955e-02,
|
| 2824 |
+
6.6658e-02,
|
| 2825 |
+
-4.6417e-02,
|
| 2826 |
+
1.0408e-01,
|
| 2827 |
+
-1.1210e-01,
|
| 2828 |
+
-3.3793e-02,
|
| 2829 |
+
-1.6235e-01,
|
| 2830 |
+
7.3353e-02,
|
| 2831 |
+
4.5024e-02,
|
| 2832 |
+
-7.6526e-02,
|
| 2833 |
+
-3.0443e-02,
|
| 2834 |
+
1.2222e-01,
|
| 2835 |
+
1.1513e-02,
|
| 2836 |
+
-8.5835e-02,
|
| 2837 |
+
5.6084e-02,
|
| 2838 |
+
-6.5380e-02,
|
| 2839 |
+
1.3535e-01,
|
| 2840 |
+
7.2861e-02,
|
| 2841 |
+
-4.8121e-02,
|
| 2842 |
+
6.6781e-02,
|
| 2843 |
+
2.5041e-01,
|
| 2844 |
+
9.3076e-02,
|
| 2845 |
+
-2.0334e-02,
|
| 2846 |
+
-1.0416e-01,
|
| 2847 |
+
-3.9805e-02,
|
| 2848 |
+
-1.0051e-01,
|
| 2849 |
+
-9.2133e-02,
|
| 2850 |
+
6.3271e-02,
|
| 2851 |
+
3.4768e-02,
|
| 2852 |
+
1.1286e-01,
|
| 2853 |
+
1.3493e-02,
|
| 2854 |
+
3.0643e-02,
|
| 2855 |
+
-5.5867e-02,
|
| 2856 |
+
2.4630e-02,
|
| 2857 |
+
7.8038e-02,
|
| 2858 |
+
-7.5769e-02,
|
| 2859 |
+
9.0636e-02,
|
| 2860 |
+
1.8840e-02,
|
| 2861 |
+
1.3688e-02,
|
| 2862 |
+
1.2780e-01,
|
| 2863 |
+
-4.3306e-02,
|
| 2864 |
+
7.6513e-02,
|
| 2865 |
+
5.6990e-02,
|
| 2866 |
+
8.7927e-02,
|
| 2867 |
+
1.6438e-03,
|
| 2868 |
+
-1.0833e-02,
|
| 2869 |
+
1.3722e-01,
|
| 2870 |
+
-9.4365e-02,
|
| 2871 |
+
-7.4534e-02,
|
| 2872 |
+
-6.2697e-02,
|
| 2873 |
+
1.6868e-01,
|
| 2874 |
+
1.6850e-01,
|
| 2875 |
+
4.3229e-02,
|
| 2876 |
+
7.4762e-02,
|
| 2877 |
+
1.1225e-01,
|
| 2878 |
+
-1.9559e-01,
|
| 2879 |
+
1.1981e-01,
|
| 2880 |
+
5.0025e-02,
|
| 2881 |
+
],
|
| 2882 |
+
[
|
| 2883 |
+
1.0233e-01,
|
| 2884 |
+
6.7397e-02,
|
| 2885 |
+
1.0132e-01,
|
| 2886 |
+
1.1631e-01,
|
| 2887 |
+
4.3957e-02,
|
| 2888 |
+
5.7017e-02,
|
| 2889 |
+
-4.0769e-02,
|
| 2890 |
+
-1.2329e-01,
|
| 2891 |
+
-6.1235e-03,
|
| 2892 |
+
1.3821e-01,
|
| 2893 |
+
1.3135e-01,
|
| 2894 |
+
-7.2640e-02,
|
| 2895 |
+
6.7380e-02,
|
| 2896 |
+
4.7518e-02,
|
| 2897 |
+
-1.0261e-01,
|
| 2898 |
+
-8.4497e-02,
|
| 2899 |
+
1.1074e-01,
|
| 2900 |
+
7.9965e-02,
|
| 2901 |
+
4.3208e-03,
|
| 2902 |
+
-7.9881e-03,
|
| 2903 |
+
3.0558e-02,
|
| 2904 |
+
3.8130e-02,
|
| 2905 |
+
-7.0863e-02,
|
| 2906 |
+
2.6484e-02,
|
| 2907 |
+
-8.1795e-02,
|
| 2908 |
+
3.9067e-02,
|
| 2909 |
+
-1.5670e-01,
|
| 2910 |
+
1.2963e-01,
|
| 2911 |
+
4.3868e-03,
|
| 2912 |
+
1.3081e-01,
|
| 2913 |
+
1.7308e-01,
|
| 2914 |
+
5.3891e-02,
|
| 2915 |
+
-1.2683e-01,
|
| 2916 |
+
6.0787e-02,
|
| 2917 |
+
-7.8336e-02,
|
| 2918 |
+
-1.0347e-01,
|
| 2919 |
+
5.8472e-02,
|
| 2920 |
+
-2.7212e-02,
|
| 2921 |
+
7.1385e-02,
|
| 2922 |
+
-6.8297e-03,
|
| 2923 |
+
8.7485e-02,
|
| 2924 |
+
-7.1364e-02,
|
| 2925 |
+
-1.9182e-02,
|
| 2926 |
+
8.7217e-02,
|
| 2927 |
+
8.2944e-02,
|
| 2928 |
+
3.4400e-02,
|
| 2929 |
+
-8.5778e-03,
|
| 2930 |
+
-1.1191e-01,
|
| 2931 |
+
1.4871e-01,
|
| 2932 |
+
1.0602e-01,
|
| 2933 |
+
5.5060e-02,
|
| 2934 |
+
4.0554e-02,
|
| 2935 |
+
-1.0835e-01,
|
| 2936 |
+
-1.4749e-01,
|
| 2937 |
+
1.1336e-01,
|
| 2938 |
+
8.1897e-03,
|
| 2939 |
+
-5.1693e-02,
|
| 2940 |
+
4.9600e-02,
|
| 2941 |
+
-3.6377e-02,
|
| 2942 |
+
-1.6864e-03,
|
| 2943 |
+
-1.4149e-01,
|
| 2944 |
+
-3.8906e-02,
|
| 2945 |
+
5.3481e-02,
|
| 2946 |
+
-1.1160e-01,
|
| 2947 |
+
1.3861e-01,
|
| 2948 |
+
6.3040e-02,
|
| 2949 |
+
-2.2296e-02,
|
| 2950 |
+
8.1680e-02,
|
| 2951 |
+
7.9567e-02,
|
| 2952 |
+
-6.1083e-02,
|
| 2953 |
+
6.7573e-02,
|
| 2954 |
+
9.8196e-02,
|
| 2955 |
+
-7.0956e-02,
|
| 2956 |
+
8.7717e-02,
|
| 2957 |
+
-1.3439e-01,
|
| 2958 |
+
-4.4087e-02,
|
| 2959 |
+
-1.7677e-01,
|
| 2960 |
+
5.1971e-02,
|
| 2961 |
+
1.1013e-01,
|
| 2962 |
+
-1.2838e-01,
|
| 2963 |
+
-1.8450e-02,
|
| 2964 |
+
9.7373e-02,
|
| 2965 |
+
1.5415e-02,
|
| 2966 |
+
-6.8535e-02,
|
| 2967 |
+
5.8374e-02,
|
| 2968 |
+
-1.0450e-01,
|
| 2969 |
+
1.3363e-01,
|
| 2970 |
+
1.2089e-01,
|
| 2971 |
+
-4.1817e-02,
|
| 2972 |
+
3.1015e-02,
|
| 2973 |
+
2.7185e-01,
|
| 2974 |
+
6.9890e-02,
|
| 2975 |
+
-3.8259e-03,
|
| 2976 |
+
-7.7094e-02,
|
| 2977 |
+
2.4651e-02,
|
| 2978 |
+
-1.0086e-01,
|
| 2979 |
+
-8.4380e-02,
|
| 2980 |
+
4.9062e-02,
|
| 2981 |
+
4.7470e-02,
|
| 2982 |
+
1.0739e-01,
|
| 2983 |
+
-2.4693e-03,
|
| 2984 |
+
-5.9990e-02,
|
| 2985 |
+
-6.2990e-02,
|
| 2986 |
+
1.2398e-03,
|
| 2987 |
+
4.8100e-03,
|
| 2988 |
+
-6.0338e-02,
|
| 2989 |
+
6.4579e-02,
|
| 2990 |
+
4.2505e-04,
|
| 2991 |
+
-2.9926e-02,
|
| 2992 |
+
1.3627e-01,
|
| 2993 |
+
-3.0724e-02,
|
| 2994 |
+
4.2972e-02,
|
| 2995 |
+
4.6971e-02,
|
| 2996 |
+
1.2441e-01,
|
| 2997 |
+
-2.4336e-02,
|
| 2998 |
+
6.9954e-02,
|
| 2999 |
+
1.0403e-01,
|
| 3000 |
+
-3.2450e-02,
|
| 3001 |
+
-4.3154e-02,
|
| 3002 |
+
-4.9959e-02,
|
| 3003 |
+
1.5666e-01,
|
| 3004 |
+
1.3688e-01,
|
| 3005 |
+
5.3450e-02,
|
| 3006 |
+
7.9968e-02,
|
| 3007 |
+
1.3858e-01,
|
| 3008 |
+
-1.6817e-01,
|
| 3009 |
+
1.2637e-01,
|
| 3010 |
+
7.3937e-02,
|
| 3011 |
+
],
|
| 3012 |
+
]
|
| 3013 |
+
)
|
src/backend/vespa_app.py
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import time
|
| 3 |
+
from typing import Any, Dict, Tuple
|
| 4 |
+
import asyncio
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
from vespa.application import Vespa
|
| 9 |
+
from vespa.io import VespaQueryResponse
|
| 10 |
+
from .colpali import SimMapGenerator
|
| 11 |
+
import backend.stopwords
|
| 12 |
+
import logging
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class VespaQueryClient:
|
| 16 |
+
MAX_QUERY_TERMS = 64
|
| 17 |
+
VESPA_SCHEMA_NAME = "pdf_page"
|
| 18 |
+
SELECT_FIELDS = "id,title,url,blur_image,page_number,snippet,text"
|
| 19 |
+
|
| 20 |
+
def __init__(self, logger: logging.Logger):
|
| 21 |
+
"""
|
| 22 |
+
Initialize the VespaQueryClient by loading environment variables and establishing a connection to the Vespa application.
|
| 23 |
+
"""
|
| 24 |
+
load_dotenv()
|
| 25 |
+
self.logger = logger
|
| 26 |
+
|
| 27 |
+
if os.environ.get("USE_MTLS") == "true":
|
| 28 |
+
self.logger.info("Connected using mTLS")
|
| 29 |
+
mtls_key = os.environ.get("VESPA_CLOUD_MTLS_KEY")
|
| 30 |
+
mtls_cert = os.environ.get("VESPA_CLOUD_MTLS_CERT")
|
| 31 |
+
|
| 32 |
+
self.vespa_app_url = os.environ.get("VESPA_APP_MTLS_URL")
|
| 33 |
+
if not self.vespa_app_url:
|
| 34 |
+
raise ValueError(
|
| 35 |
+
"Please set the VESPA_APP_MTLS_URL environment variable"
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
if not mtls_cert or not mtls_key:
|
| 39 |
+
raise ValueError(
|
| 40 |
+
"USE_MTLS was true, but VESPA_CLOUD_MTLS_KEY and VESPA_CLOUD_MTLS_CERT were not set"
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# write the key and cert to a file
|
| 44 |
+
mtls_key_path = "/tmp/vespa-data-plane-private-key.pem"
|
| 45 |
+
with open(mtls_key_path, "w") as f:
|
| 46 |
+
f.write(mtls_key)
|
| 47 |
+
|
| 48 |
+
mtls_cert_path = "/tmp/vespa-data-plane-public-cert.pem"
|
| 49 |
+
with open(mtls_cert_path, "w") as f:
|
| 50 |
+
f.write(mtls_cert)
|
| 51 |
+
|
| 52 |
+
# Instantiate Vespa connection
|
| 53 |
+
self.app = Vespa(
|
| 54 |
+
url=self.vespa_app_url, key=mtls_key_path, cert=mtls_cert_path
|
| 55 |
+
)
|
| 56 |
+
else:
|
| 57 |
+
self.logger.info("Connected using token")
|
| 58 |
+
self.vespa_app_url = os.environ.get("VESPA_APP_TOKEN_URL")
|
| 59 |
+
if not self.vespa_app_url:
|
| 60 |
+
raise ValueError(
|
| 61 |
+
"Please set the VESPA_APP_TOKEN_URL environment variable"
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
self.vespa_cloud_secret_token = os.environ.get("VESPA_CLOUD_SECRET_TOKEN")
|
| 65 |
+
|
| 66 |
+
if not self.vespa_cloud_secret_token:
|
| 67 |
+
raise ValueError(
|
| 68 |
+
"Please set the VESPA_CLOUD_SECRET_TOKEN environment variable"
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
# Instantiate Vespa connection
|
| 72 |
+
self.app = Vespa(
|
| 73 |
+
url=self.vespa_app_url,
|
| 74 |
+
vespa_cloud_secret_token=self.vespa_cloud_secret_token,
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
self.app.wait_for_application_up()
|
| 78 |
+
self.logger.info(f"Connected to Vespa at {self.vespa_app_url}")
|
| 79 |
+
|
| 80 |
+
def get_fields(self, sim_map: bool = False):
|
| 81 |
+
if not sim_map:
|
| 82 |
+
return self.SELECT_FIELDS
|
| 83 |
+
else:
|
| 84 |
+
return "summaryfeatures"
|
| 85 |
+
|
| 86 |
+
def format_query_results(
|
| 87 |
+
self, query: str, response: VespaQueryResponse, hits: int = 5
|
| 88 |
+
) -> dict:
|
| 89 |
+
"""
|
| 90 |
+
Format the Vespa query results.
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
query (str): The query text.
|
| 94 |
+
response (VespaQueryResponse): The response from Vespa.
|
| 95 |
+
hits (int, optional): Number of hits to display. Defaults to 5.
|
| 96 |
+
|
| 97 |
+
Returns:
|
| 98 |
+
dict: The JSON content of the response.
|
| 99 |
+
"""
|
| 100 |
+
query_time = response.json.get("timing", {}).get("searchtime", -1)
|
| 101 |
+
query_time = round(query_time, 2)
|
| 102 |
+
count = response.json.get("root", {}).get("fields", {}).get("totalCount", 0)
|
| 103 |
+
result_text = f"Query text: '{query}', query time {query_time}s, count={count}, top results:\n"
|
| 104 |
+
self.logger.debug(result_text)
|
| 105 |
+
return response.json
|
| 106 |
+
|
| 107 |
+
async def query_vespa_bm25(
|
| 108 |
+
self,
|
| 109 |
+
query: str,
|
| 110 |
+
q_emb: torch.Tensor,
|
| 111 |
+
hits: int = 3,
|
| 112 |
+
timeout: str = "10s",
|
| 113 |
+
sim_map: bool = False,
|
| 114 |
+
**kwargs,
|
| 115 |
+
) -> dict:
|
| 116 |
+
"""
|
| 117 |
+
Query Vespa using the BM25 ranking profile.
|
| 118 |
+
This corresponds to the "BM25" radio button in the UI.
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
query (str): The query text.
|
| 122 |
+
q_emb (torch.Tensor): Query embeddings.
|
| 123 |
+
hits (int, optional): Number of hits to retrieve. Defaults to 3.
|
| 124 |
+
timeout (str, optional): Query timeout. Defaults to "10s".
|
| 125 |
+
|
| 126 |
+
Returns:
|
| 127 |
+
dict: The formatted query results.
|
| 128 |
+
"""
|
| 129 |
+
async with self.app.asyncio(connections=1) as session:
|
| 130 |
+
query_embedding = self.format_q_embs(q_emb)
|
| 131 |
+
|
| 132 |
+
start = time.perf_counter()
|
| 133 |
+
response: VespaQueryResponse = await session.query(
|
| 134 |
+
body={
|
| 135 |
+
"yql": (
|
| 136 |
+
f"select {self.get_fields(sim_map=sim_map)} from {self.VESPA_SCHEMA_NAME} where userQuery();"
|
| 137 |
+
),
|
| 138 |
+
"ranking": self.get_rank_profile("bm25", sim_map),
|
| 139 |
+
"query": query,
|
| 140 |
+
"timeout": timeout,
|
| 141 |
+
"hits": hits,
|
| 142 |
+
"input.query(qt)": query_embedding,
|
| 143 |
+
"presentation.timing": True,
|
| 144 |
+
**kwargs,
|
| 145 |
+
},
|
| 146 |
+
)
|
| 147 |
+
assert response.is_successful(), response.json
|
| 148 |
+
stop = time.perf_counter()
|
| 149 |
+
self.logger.debug(
|
| 150 |
+
f"Query time + data transfer took: {stop - start} s, Vespa reported searchtime was "
|
| 151 |
+
f"{response.json.get('timing', {}).get('searchtime', -1)} s"
|
| 152 |
+
)
|
| 153 |
+
return self.format_query_results(query, response)
|
| 154 |
+
|
| 155 |
+
def float_to_binary_embedding(self, float_query_embedding: dict) -> dict:
|
| 156 |
+
"""
|
| 157 |
+
Convert float query embeddings to binary embeddings.
|
| 158 |
+
|
| 159 |
+
Args:
|
| 160 |
+
float_query_embedding (dict): Dictionary of float embeddings.
|
| 161 |
+
|
| 162 |
+
Returns:
|
| 163 |
+
dict: Dictionary of binary embeddings.
|
| 164 |
+
"""
|
| 165 |
+
binary_query_embeddings = {}
|
| 166 |
+
for key, vector in float_query_embedding.items():
|
| 167 |
+
binary_vector = (
|
| 168 |
+
np.packbits(np.where(np.array(vector) > 0, 1, 0))
|
| 169 |
+
.astype(np.int8)
|
| 170 |
+
.tolist()
|
| 171 |
+
)
|
| 172 |
+
binary_query_embeddings[key] = binary_vector
|
| 173 |
+
if len(binary_query_embeddings) >= self.MAX_QUERY_TERMS:
|
| 174 |
+
self.logger.warning(
|
| 175 |
+
f"Warning: Query has more than {self.MAX_QUERY_TERMS} terms. Truncating."
|
| 176 |
+
)
|
| 177 |
+
break
|
| 178 |
+
return binary_query_embeddings
|
| 179 |
+
|
| 180 |
+
def create_nn_query_strings(
|
| 181 |
+
self, binary_query_embeddings: dict, target_hits_per_query_tensor: int = 20
|
| 182 |
+
) -> Tuple[str, dict]:
|
| 183 |
+
"""
|
| 184 |
+
Create nearest neighbor query strings for Vespa.
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
binary_query_embeddings (dict): Binary query embeddings.
|
| 188 |
+
target_hits_per_query_tensor (int, optional): Target hits per query tensor. Defaults to 20.
|
| 189 |
+
|
| 190 |
+
Returns:
|
| 191 |
+
Tuple[str, dict]: Nearest neighbor query string and query tensor dictionary.
|
| 192 |
+
"""
|
| 193 |
+
nn_query_dict = {}
|
| 194 |
+
for i in range(len(binary_query_embeddings)):
|
| 195 |
+
nn_query_dict[f"input.query(rq{i})"] = binary_query_embeddings[i]
|
| 196 |
+
nn = " OR ".join(
|
| 197 |
+
[
|
| 198 |
+
f"({{targetHits:{target_hits_per_query_tensor}}}nearestNeighbor(embedding,rq{i}))"
|
| 199 |
+
for i in range(len(binary_query_embeddings))
|
| 200 |
+
]
|
| 201 |
+
)
|
| 202 |
+
return nn, nn_query_dict
|
| 203 |
+
|
| 204 |
+
def format_q_embs(self, q_embs: torch.Tensor) -> dict:
|
| 205 |
+
"""
|
| 206 |
+
Convert query embeddings to a dictionary of lists.
|
| 207 |
+
|
| 208 |
+
Args:
|
| 209 |
+
q_embs (torch.Tensor): Query embeddings tensor.
|
| 210 |
+
|
| 211 |
+
Returns:
|
| 212 |
+
dict: Dictionary where each key is an index and value is the embedding list.
|
| 213 |
+
"""
|
| 214 |
+
return {idx: emb.tolist() for idx, emb in enumerate(q_embs)}
|
| 215 |
+
|
| 216 |
+
async def get_result_from_query(
|
| 217 |
+
self,
|
| 218 |
+
query: str,
|
| 219 |
+
q_embs: torch.Tensor,
|
| 220 |
+
ranking: str,
|
| 221 |
+
idx_to_token: dict,
|
| 222 |
+
) -> Dict[str, Any]:
|
| 223 |
+
"""
|
| 224 |
+
Get query results from Vespa based on the ranking method.
|
| 225 |
+
|
| 226 |
+
Args:
|
| 227 |
+
query (str): The query text.
|
| 228 |
+
q_embs (torch.Tensor): Query embeddings.
|
| 229 |
+
ranking (str): The ranking method to use.
|
| 230 |
+
idx_to_token (dict): Index to token mapping.
|
| 231 |
+
|
| 232 |
+
Returns:
|
| 233 |
+
Dict[str, Any]: The query results.
|
| 234 |
+
"""
|
| 235 |
+
|
| 236 |
+
# Remove stopwords from the query to avoid visual emphasis on irrelevant words (e.g., "the", "and", "of")
|
| 237 |
+
query = backend.stopwords.filter(query)
|
| 238 |
+
|
| 239 |
+
rank_method = ranking.split("_")[0]
|
| 240 |
+
sim_map: bool = len(ranking.split("_")) > 1 and ranking.split("_")[1] == "sim"
|
| 241 |
+
if rank_method == "colpali": # ColPali
|
| 242 |
+
result = await self.query_vespa_colpali(
|
| 243 |
+
query=query, ranking=rank_method, q_emb=q_embs, sim_map=sim_map
|
| 244 |
+
)
|
| 245 |
+
elif rank_method == "hybrid": # Hybrid ColPali+BM25
|
| 246 |
+
result = await self.query_vespa_colpali(
|
| 247 |
+
query=query, ranking=rank_method, q_emb=q_embs, sim_map=sim_map
|
| 248 |
+
)
|
| 249 |
+
elif rank_method == "bm25":
|
| 250 |
+
result = await self.query_vespa_bm25(query, q_embs, sim_map=sim_map)
|
| 251 |
+
else:
|
| 252 |
+
raise ValueError(f"Unsupported ranking: {rank_method}")
|
| 253 |
+
if "root" not in result or "children" not in result["root"]:
|
| 254 |
+
result["root"] = {"children": []}
|
| 255 |
+
return result
|
| 256 |
+
for single_result in result["root"]["children"]:
|
| 257 |
+
self.logger.debug(single_result["fields"].keys())
|
| 258 |
+
return result
|
| 259 |
+
|
| 260 |
+
def get_sim_maps_from_query(
|
| 261 |
+
self, query: str, q_embs: torch.Tensor, ranking: str, idx_to_token: dict
|
| 262 |
+
):
|
| 263 |
+
"""
|
| 264 |
+
Get similarity maps from Vespa based on the ranking method.
|
| 265 |
+
|
| 266 |
+
Args:
|
| 267 |
+
query (str): The query text.
|
| 268 |
+
q_embs (torch.Tensor): Query embeddings.
|
| 269 |
+
ranking (str): The ranking method to use.
|
| 270 |
+
idx_to_token (dict): Index to token mapping.
|
| 271 |
+
|
| 272 |
+
Returns:
|
| 273 |
+
Dict[str, Any]: The query results.
|
| 274 |
+
"""
|
| 275 |
+
# Get the result by calling asyncio.run
|
| 276 |
+
result = asyncio.run(
|
| 277 |
+
self.get_result_from_query(query, q_embs, ranking, idx_to_token)
|
| 278 |
+
)
|
| 279 |
+
vespa_sim_maps = []
|
| 280 |
+
for single_result in result["root"]["children"]:
|
| 281 |
+
vespa_sim_map = single_result["fields"].get("summaryfeatures", None)
|
| 282 |
+
if vespa_sim_map is not None:
|
| 283 |
+
vespa_sim_maps.append(vespa_sim_map)
|
| 284 |
+
else:
|
| 285 |
+
raise ValueError("No sim_map found in Vespa response")
|
| 286 |
+
return vespa_sim_maps
|
| 287 |
+
|
| 288 |
+
async def get_full_image_from_vespa(self, doc_id: str) -> str:
|
| 289 |
+
"""
|
| 290 |
+
Retrieve the full image from Vespa for a given document ID.
|
| 291 |
+
|
| 292 |
+
Args:
|
| 293 |
+
doc_id (str): The document ID.
|
| 294 |
+
|
| 295 |
+
Returns:
|
| 296 |
+
str: The full image data.
|
| 297 |
+
"""
|
| 298 |
+
async with self.app.asyncio(connections=1) as session:
|
| 299 |
+
start = time.perf_counter()
|
| 300 |
+
response: VespaQueryResponse = await session.query(
|
| 301 |
+
body={
|
| 302 |
+
"yql": f'select full_image from {self.VESPA_SCHEMA_NAME} where id contains "{doc_id}"',
|
| 303 |
+
"ranking": "unranked",
|
| 304 |
+
"presentation.timing": True,
|
| 305 |
+
"ranking.matching.numThreadsPerSearch": 1,
|
| 306 |
+
},
|
| 307 |
+
)
|
| 308 |
+
assert response.is_successful(), response.json
|
| 309 |
+
stop = time.perf_counter()
|
| 310 |
+
self.logger.debug(
|
| 311 |
+
f"Getting image from Vespa took: {stop - start} s, Vespa reported searchtime was "
|
| 312 |
+
f"{response.json.get('timing', {}).get('searchtime', -1)} s"
|
| 313 |
+
)
|
| 314 |
+
return response.json["root"]["children"][0]["fields"]["full_image"]
|
| 315 |
+
|
| 316 |
+
def get_results_children(self, result: VespaQueryResponse) -> list:
|
| 317 |
+
return result["root"]["children"]
|
| 318 |
+
|
| 319 |
+
def results_to_search_results(
|
| 320 |
+
self, result: VespaQueryResponse, idx_to_token: dict
|
| 321 |
+
) -> list:
|
| 322 |
+
# Initialize sim_map_ fields in the result
|
| 323 |
+
fields_to_add = [
|
| 324 |
+
f"sim_map_{token}_{idx}"
|
| 325 |
+
for idx, token in idx_to_token.items()
|
| 326 |
+
if not SimMapGenerator.should_filter_token(token)
|
| 327 |
+
]
|
| 328 |
+
for child in result["root"]["children"]:
|
| 329 |
+
for sim_map_key in fields_to_add:
|
| 330 |
+
child["fields"][sim_map_key] = None
|
| 331 |
+
return self.get_results_children(result)
|
| 332 |
+
|
| 333 |
+
async def get_suggestions(self, query: str) -> list:
|
| 334 |
+
async with self.app.asyncio(connections=1) as session:
|
| 335 |
+
start = time.perf_counter()
|
| 336 |
+
yql = f'select questions from {self.VESPA_SCHEMA_NAME} where questions matches (".*{query}.*")'
|
| 337 |
+
response: VespaQueryResponse = await session.query(
|
| 338 |
+
body={
|
| 339 |
+
"yql": yql,
|
| 340 |
+
"query": query,
|
| 341 |
+
"ranking": "unranked",
|
| 342 |
+
"presentation.timing": True,
|
| 343 |
+
"presentation.summary": "suggestions",
|
| 344 |
+
"ranking.matching.numThreadsPerSearch": 1,
|
| 345 |
+
},
|
| 346 |
+
)
|
| 347 |
+
assert response.is_successful(), response.json
|
| 348 |
+
stop = time.perf_counter()
|
| 349 |
+
self.logger.debug(
|
| 350 |
+
f"Getting suggestions from Vespa took: {stop - start} s, Vespa reported searchtime was "
|
| 351 |
+
f"{response.json.get('timing', {}).get('searchtime', -1)} s"
|
| 352 |
+
)
|
| 353 |
+
search_results = (
|
| 354 |
+
response.json["root"]["children"]
|
| 355 |
+
if "root" in response.json and "children" in response.json["root"]
|
| 356 |
+
else []
|
| 357 |
+
)
|
| 358 |
+
questions = [
|
| 359 |
+
result["fields"]["questions"]
|
| 360 |
+
for result in search_results
|
| 361 |
+
if "questions" in result["fields"]
|
| 362 |
+
]
|
| 363 |
+
|
| 364 |
+
unique_questions = set([item for sublist in questions for item in sublist])
|
| 365 |
+
|
| 366 |
+
# remove an artifact from our data generation
|
| 367 |
+
if "string" in unique_questions:
|
| 368 |
+
unique_questions.remove("string")
|
| 369 |
+
|
| 370 |
+
return list(unique_questions)
|
| 371 |
+
|
| 372 |
+
def get_rank_profile(self, ranking: str, sim_map: bool) -> str:
|
| 373 |
+
if sim_map:
|
| 374 |
+
return f"{ranking}_sim"
|
| 375 |
+
else:
|
| 376 |
+
return ranking
|
| 377 |
+
|
| 378 |
+
async def query_vespa_colpali(
|
| 379 |
+
self,
|
| 380 |
+
query: str,
|
| 381 |
+
ranking: str,
|
| 382 |
+
q_emb: torch.Tensor,
|
| 383 |
+
target_hits_per_query_tensor: int = 100,
|
| 384 |
+
hnsw_explore_additional_hits: int = 300,
|
| 385 |
+
hits: int = 3,
|
| 386 |
+
timeout: str = "10s",
|
| 387 |
+
sim_map: bool = False,
|
| 388 |
+
**kwargs,
|
| 389 |
+
) -> dict:
|
| 390 |
+
"""
|
| 391 |
+
Query Vespa using nearest neighbor search with mixed tensors for MaxSim calculations.
|
| 392 |
+
This corresponds to the "ColPali" radio button in the UI.
|
| 393 |
+
|
| 394 |
+
Args:
|
| 395 |
+
query (str): The query text.
|
| 396 |
+
q_emb (torch.Tensor): Query embeddings.
|
| 397 |
+
target_hits_per_query_tensor (int, optional): Target hits per query tensor. Defaults to 20.
|
| 398 |
+
hits (int, optional): Number of hits to retrieve. Defaults to 3.
|
| 399 |
+
timeout (str, optional): Query timeout. Defaults to "10s".
|
| 400 |
+
|
| 401 |
+
Returns:
|
| 402 |
+
dict: The formatted query results.
|
| 403 |
+
"""
|
| 404 |
+
async with self.app.asyncio(connections=1) as session:
|
| 405 |
+
float_query_embedding = self.format_q_embs(q_emb)
|
| 406 |
+
binary_query_embeddings = self.float_to_binary_embedding(
|
| 407 |
+
float_query_embedding
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
# Mixed tensors for MaxSim calculations
|
| 411 |
+
query_tensors = {
|
| 412 |
+
"input.query(qtb)": binary_query_embeddings,
|
| 413 |
+
"input.query(qt)": float_query_embedding,
|
| 414 |
+
}
|
| 415 |
+
nn_string, nn_query_dict = self.create_nn_query_strings(
|
| 416 |
+
binary_query_embeddings, target_hits_per_query_tensor
|
| 417 |
+
)
|
| 418 |
+
query_tensors.update(nn_query_dict)
|
| 419 |
+
response: VespaQueryResponse = await session.query(
|
| 420 |
+
body={
|
| 421 |
+
**query_tensors,
|
| 422 |
+
"presentation.timing": True,
|
| 423 |
+
"yql": (
|
| 424 |
+
f"select {self.get_fields(sim_map=sim_map)} from {self.VESPA_SCHEMA_NAME} where {nn_string} or userQuery()"
|
| 425 |
+
),
|
| 426 |
+
"ranking.profile": self.get_rank_profile(
|
| 427 |
+
ranking=ranking, sim_map=sim_map
|
| 428 |
+
),
|
| 429 |
+
"timeout": timeout,
|
| 430 |
+
"hits": hits,
|
| 431 |
+
"query": query,
|
| 432 |
+
"hnsw.exploreAdditionalHits": hnsw_explore_additional_hits,
|
| 433 |
+
"ranking.rerankCount": 100,
|
| 434 |
+
**kwargs,
|
| 435 |
+
},
|
| 436 |
+
)
|
| 437 |
+
assert response.is_successful(), response.json
|
| 438 |
+
return self.format_query_results(query, response)
|
| 439 |
+
|
| 440 |
+
async def keepalive(self) -> bool:
|
| 441 |
+
"""
|
| 442 |
+
Query Vespa to keep the connection alive.
|
| 443 |
+
|
| 444 |
+
Returns:
|
| 445 |
+
bool: True if the connection is alive.
|
| 446 |
+
"""
|
| 447 |
+
async with self.app.asyncio(connections=1) as session:
|
| 448 |
+
response: VespaQueryResponse = await session.query(
|
| 449 |
+
body={
|
| 450 |
+
"yql": f"select title from {self.VESPA_SCHEMA_NAME} where true limit 1;",
|
| 451 |
+
"ranking": "unranked",
|
| 452 |
+
"query": "keepalive",
|
| 453 |
+
"timeout": "3s",
|
| 454 |
+
"hits": 1,
|
| 455 |
+
},
|
| 456 |
+
)
|
| 457 |
+
assert response.is_successful(), response.json
|
| 458 |
+
return True
|
src/frontend/__init__.py
ADDED
|
File without changes
|
src/frontend/app.py
ADDED
|
@@ -0,0 +1,768 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
from urllib.parse import quote_plus
|
| 3 |
+
|
| 4 |
+
from fasthtml.components import (
|
| 5 |
+
H1,
|
| 6 |
+
H2,
|
| 7 |
+
H3,
|
| 8 |
+
Br,
|
| 9 |
+
Div,
|
| 10 |
+
Form,
|
| 11 |
+
Img,
|
| 12 |
+
NotStr,
|
| 13 |
+
P,
|
| 14 |
+
Hr,
|
| 15 |
+
Span,
|
| 16 |
+
A,
|
| 17 |
+
Script,
|
| 18 |
+
Button,
|
| 19 |
+
Label,
|
| 20 |
+
RadioGroup,
|
| 21 |
+
RadioGroupItem,
|
| 22 |
+
Separator,
|
| 23 |
+
Ul,
|
| 24 |
+
Li,
|
| 25 |
+
Strong,
|
| 26 |
+
Iframe,
|
| 27 |
+
)
|
| 28 |
+
from fasthtml.xtend import A, Script
|
| 29 |
+
from lucide_fasthtml import Lucide
|
| 30 |
+
from shad4fast import Badge, Button, Input, Label, RadioGroup, RadioGroupItem, Separator
|
| 31 |
+
|
| 32 |
+
# JavaScript to check the input value and enable/disable the search button and radio buttons
|
| 33 |
+
check_input_script = Script(
|
| 34 |
+
"""
|
| 35 |
+
window.onload = function() {
|
| 36 |
+
const input = document.getElementById('search-input');
|
| 37 |
+
const button = document.querySelector('[data-button="search-button"]');
|
| 38 |
+
const radioGroupItems = document.querySelectorAll('button[data-ref="radio-item"]'); // Get all radio buttons
|
| 39 |
+
|
| 40 |
+
function checkInputValue() {
|
| 41 |
+
const isInputEmpty = input.value.trim() === "";
|
| 42 |
+
button.disabled = isInputEmpty; // Disable the submit button
|
| 43 |
+
radioGroupItems.forEach(item => {
|
| 44 |
+
item.disabled = isInputEmpty; // Disable/enable the radio buttons
|
| 45 |
+
});
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
input.addEventListener('input', checkInputValue); // Listen for input changes
|
| 49 |
+
checkInputValue(); // Initial check when the page loads
|
| 50 |
+
};
|
| 51 |
+
"""
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
# JavaScript to handle the image swapping, reset button, and active class toggling
|
| 55 |
+
image_swapping = Script(
|
| 56 |
+
"""
|
| 57 |
+
document.addEventListener('click', function (e) {
|
| 58 |
+
if (e.target.classList.contains('sim-map-button') || e.target.classList.contains('reset-button')) {
|
| 59 |
+
const imgContainer = e.target.closest('.relative');
|
| 60 |
+
const overlayContainer = imgContainer.querySelector('.overlay-container');
|
| 61 |
+
const newSrc = e.target.getAttribute('data-image-src');
|
| 62 |
+
|
| 63 |
+
// If it's a reset button, remove the overlay image
|
| 64 |
+
if (e.target.classList.contains('reset-button')) {
|
| 65 |
+
overlayContainer.innerHTML = ''; // Clear the overlay container, showing only the full image
|
| 66 |
+
} else {
|
| 67 |
+
// Create a new overlay image
|
| 68 |
+
const img = document.createElement('img');
|
| 69 |
+
img.src = newSrc;
|
| 70 |
+
img.classList.add('overlay-image', 'absolute', 'top-0', 'left-0', 'w-full', 'h-full');
|
| 71 |
+
overlayContainer.innerHTML = ''; // Clear any previous overlay
|
| 72 |
+
overlayContainer.appendChild(img); // Add the new overlay image
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
// Toggle active class on buttons
|
| 76 |
+
const activeButton = document.querySelector('.sim-map-button.active');
|
| 77 |
+
if (activeButton) {
|
| 78 |
+
activeButton.classList.remove('active');
|
| 79 |
+
}
|
| 80 |
+
if (e.target.classList.contains('sim-map-button')) {
|
| 81 |
+
e.target.classList.add('active');
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
});
|
| 85 |
+
"""
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
toggle_text_content = Script(
|
| 89 |
+
"""
|
| 90 |
+
function toggleTextContent(idx) {
|
| 91 |
+
const textColumn = document.getElementById(`text-column-${idx}`);
|
| 92 |
+
const imageTextColumns = document.getElementById(`image-text-columns-${idx}`);
|
| 93 |
+
const toggleButton = document.getElementById(`toggle-button-${idx}`);
|
| 94 |
+
|
| 95 |
+
if (textColumn.classList.contains('md-grid-text-column')) {
|
| 96 |
+
// Hide the text column
|
| 97 |
+
textColumn.classList.remove('md-grid-text-column');
|
| 98 |
+
imageTextColumns.classList.remove('grid-image-text-columns');
|
| 99 |
+
toggleButton.innerText = `Show Text`;
|
| 100 |
+
} else {
|
| 101 |
+
// Show the text column
|
| 102 |
+
textColumn.classList.add('md-grid-text-column');
|
| 103 |
+
imageTextColumns.classList.add('grid-image-text-columns');
|
| 104 |
+
toggleButton.innerText = `Hide Text`;
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
"""
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
autocomplete_script = Script(
|
| 111 |
+
"""
|
| 112 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 113 |
+
const input = document.querySelector('#search-input');
|
| 114 |
+
const awesomplete = new Awesomplete(input, { minChars: 1, maxItems: 5 });
|
| 115 |
+
|
| 116 |
+
input.addEventListener('input', function() {
|
| 117 |
+
if (this.value.length >= 1) {
|
| 118 |
+
// Use template literals to insert the input value dynamically in the query parameter
|
| 119 |
+
fetch(`/suggestions?query=${encodeURIComponent(this.value)}`)
|
| 120 |
+
.then(response => response.json())
|
| 121 |
+
.then(data => {
|
| 122 |
+
// Update the Awesomplete list dynamically with fetched suggestions
|
| 123 |
+
awesomplete.list = data.suggestions;
|
| 124 |
+
})
|
| 125 |
+
.catch(err => console.error('Error fetching suggestions:', err));
|
| 126 |
+
}
|
| 127 |
+
});
|
| 128 |
+
});
|
| 129 |
+
"""
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
dynamic_elements_scrollbars = Script(
|
| 133 |
+
"""
|
| 134 |
+
(function () {
|
| 135 |
+
const { applyOverlayScrollbars, getScrollbarTheme } = OverlayScrollbarsManager;
|
| 136 |
+
|
| 137 |
+
function applyScrollbarsToDynamicElements() {
|
| 138 |
+
const scrollbarTheme = getScrollbarTheme();
|
| 139 |
+
|
| 140 |
+
// Apply scrollbars to dynamically loaded result-text-full and result-text-snippet elements
|
| 141 |
+
const resultTextFullElements = document.querySelectorAll('[id^="result-text-full"]');
|
| 142 |
+
const resultTextSnippetElements = document.querySelectorAll('[id^="result-text-snippet"]');
|
| 143 |
+
|
| 144 |
+
resultTextFullElements.forEach(element => {
|
| 145 |
+
applyOverlayScrollbars(element, scrollbarTheme);
|
| 146 |
+
});
|
| 147 |
+
|
| 148 |
+
resultTextSnippetElements.forEach(element => {
|
| 149 |
+
applyOverlayScrollbars(element, scrollbarTheme);
|
| 150 |
+
});
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
// Apply scrollbars after dynamic content is loaded (e.g., after search results)
|
| 154 |
+
applyScrollbarsToDynamicElements();
|
| 155 |
+
|
| 156 |
+
// Observe changes in the 'dark' class to adjust the theme dynamically if needed
|
| 157 |
+
const observer = new MutationObserver(applyScrollbarsToDynamicElements);
|
| 158 |
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
| 159 |
+
})();
|
| 160 |
+
"""
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
+
submit_form_on_radio_change = Script(
|
| 164 |
+
"""
|
| 165 |
+
document.addEventListener('click', function (e) {
|
| 166 |
+
// if target has data-ref="radio-item" and type is button
|
| 167 |
+
if (e.target.getAttribute('data-ref') === 'radio-item' && e.target.type === 'button') {
|
| 168 |
+
console.log('Radio button clicked');
|
| 169 |
+
const form = e.target.closest('form');
|
| 170 |
+
form.submit();
|
| 171 |
+
}
|
| 172 |
+
});
|
| 173 |
+
"""
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def ShareButtons():
|
| 178 |
+
title = "Visual RAG over PDFs with Vespa and ColPali"
|
| 179 |
+
url = "https://huggingface.co/spaces/vespa-engine/colpali-vespa-visual-retrieval"
|
| 180 |
+
return Div(
|
| 181 |
+
A(
|
| 182 |
+
Img(src="/static/img/linkedin.svg", aria_hidden="true", cls="h-[21px]"),
|
| 183 |
+
"Share on LinkedIn",
|
| 184 |
+
href=f"https://www.linkedin.com/sharing/share-offsite/?url={quote_plus(url)}",
|
| 185 |
+
rel="noopener noreferrer",
|
| 186 |
+
target="_blank",
|
| 187 |
+
cls="bg-[#0A66C2] text-white inline-flex items-center gap-x-1.5 px-2.5 py-1.5 border rounded-md text-sm font-semibold",
|
| 188 |
+
),
|
| 189 |
+
A(
|
| 190 |
+
Img(src="/static/img/x.svg", aria_hidden="true", cls="h-[21px]"),
|
| 191 |
+
"Share on X",
|
| 192 |
+
href=f"https://twitter.com/intent/tweet?text={quote_plus(title)}&url={quote_plus(url)}",
|
| 193 |
+
rel="noopener noreferrer",
|
| 194 |
+
target="_blank",
|
| 195 |
+
cls="bg-black text-white inline-flex items-center gap-x-1.5 px-2.5 py-1.5 border rounded-md text-sm font-semibold",
|
| 196 |
+
),
|
| 197 |
+
cls="flex items-center justify-center space-x-8 mt-5",
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
def SearchBox(with_border=False, query_value="", ranking_value="hybrid"):
|
| 202 |
+
grid_cls = "grid gap-2 items-center p-3 bg-muted w-full"
|
| 203 |
+
|
| 204 |
+
if with_border:
|
| 205 |
+
grid_cls = "grid gap-2 p-3 rounded-md border border-input bg-muted w-full ring-offset-background focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:border-input"
|
| 206 |
+
|
| 207 |
+
return Form(
|
| 208 |
+
Div(
|
| 209 |
+
Lucide(
|
| 210 |
+
icon="search", cls="absolute left-2 top-2 text-muted-foreground z-10"
|
| 211 |
+
),
|
| 212 |
+
Input(
|
| 213 |
+
placeholder="Enter your search query...",
|
| 214 |
+
name="query",
|
| 215 |
+
value=query_value,
|
| 216 |
+
id="search-input",
|
| 217 |
+
cls="text-base pl-10 border-transparent ring-offset-transparent ring-0 focus-visible:ring-transparent bg-white dark:bg-background awesomplete",
|
| 218 |
+
data_list="#suggestions",
|
| 219 |
+
style="font-size: 1rem",
|
| 220 |
+
autofocus=True,
|
| 221 |
+
),
|
| 222 |
+
cls="relative",
|
| 223 |
+
),
|
| 224 |
+
Div(
|
| 225 |
+
Div(
|
| 226 |
+
Span("Ranking by:", cls="text-muted-foreground text-xs font-semibold"),
|
| 227 |
+
RadioGroup(
|
| 228 |
+
Div(
|
| 229 |
+
RadioGroupItem(value="colpali", id="colpali"),
|
| 230 |
+
Label("ColPali", htmlFor="ColPali"),
|
| 231 |
+
cls="flex items-center space-x-2",
|
| 232 |
+
),
|
| 233 |
+
Div(
|
| 234 |
+
RadioGroupItem(value="bm25", id="bm25"),
|
| 235 |
+
Label("BM25", htmlFor="BM25"),
|
| 236 |
+
cls="flex items-center space-x-2",
|
| 237 |
+
),
|
| 238 |
+
Div(
|
| 239 |
+
RadioGroupItem(value="hybrid", id="hybrid"),
|
| 240 |
+
Label("Hybrid ColPali + BM25", htmlFor="Hybrid ColPali + BM25"),
|
| 241 |
+
cls="flex items-center space-x-2",
|
| 242 |
+
),
|
| 243 |
+
name="ranking",
|
| 244 |
+
default_value=ranking_value,
|
| 245 |
+
cls="grid-flow-col gap-x-5 text-muted-foreground",
|
| 246 |
+
# Submit form when radio button is clicked
|
| 247 |
+
),
|
| 248 |
+
cls="grid grid-flow-col items-center gap-x-3 border border-input px-3 rounded-sm",
|
| 249 |
+
),
|
| 250 |
+
Button(
|
| 251 |
+
Lucide(icon="arrow-right", size="21"),
|
| 252 |
+
size="sm",
|
| 253 |
+
type="submit",
|
| 254 |
+
data_button="search-button",
|
| 255 |
+
disabled=True,
|
| 256 |
+
),
|
| 257 |
+
cls="flex justify-between",
|
| 258 |
+
),
|
| 259 |
+
check_input_script,
|
| 260 |
+
autocomplete_script,
|
| 261 |
+
submit_form_on_radio_change,
|
| 262 |
+
action=f"/search?query={quote_plus(query_value)}&ranking={quote_plus(ranking_value)}",
|
| 263 |
+
method="GET",
|
| 264 |
+
hx_get="/fetch_results", # As the component is a form, input components query and ranking are sent as query parameters automatically, see https://htmx.org/docs/#parameters
|
| 265 |
+
hx_trigger="load",
|
| 266 |
+
hx_target="#search-results",
|
| 267 |
+
hx_swap="outerHTML",
|
| 268 |
+
hx_indicator="#loading-indicator",
|
| 269 |
+
cls=grid_cls,
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def SampleQueries():
|
| 274 |
+
sample_queries = [
|
| 275 |
+
"What percentage of the funds unlisted real estate investments were in Switzerland 2023?",
|
| 276 |
+
"Gender balance at level 4 or above in NY office 2023?",
|
| 277 |
+
"Number of graduate applications trend 2021-2023",
|
| 278 |
+
"Total amount of fixed salaries paid in 2023?",
|
| 279 |
+
"Proportion of female new hires 2021-2023?",
|
| 280 |
+
"child jumping over puddle",
|
| 281 |
+
"hula hoop kid",
|
| 282 |
+
]
|
| 283 |
+
|
| 284 |
+
query_badges = []
|
| 285 |
+
for query in sample_queries:
|
| 286 |
+
query_badges.append(
|
| 287 |
+
A(
|
| 288 |
+
Badge(
|
| 289 |
+
Div(
|
| 290 |
+
Lucide(
|
| 291 |
+
icon="text-search", size="18", cls="text-muted-foreground"
|
| 292 |
+
),
|
| 293 |
+
Span(query, cls="text-base font-normal"),
|
| 294 |
+
cls="flex gap-2 items-center",
|
| 295 |
+
),
|
| 296 |
+
variant="outline",
|
| 297 |
+
cls="text-base font-normal text-muted-foreground hover:border-black dark:hover:border-white",
|
| 298 |
+
),
|
| 299 |
+
href=f"/search?query={quote_plus(query)}",
|
| 300 |
+
cls="no-underline",
|
| 301 |
+
)
|
| 302 |
+
)
|
| 303 |
+
|
| 304 |
+
return Div(*query_badges, cls="grid gap-2 justify-items-center")
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def Hero():
|
| 308 |
+
return Div(
|
| 309 |
+
H1(
|
| 310 |
+
"Visual RAG over PDFs",
|
| 311 |
+
cls="text-5xl md:text-6xl font-bold tracking-wide md:tracking-wider bg-clip-text text-transparent bg-gradient-to-r from-black to-slate-700 dark:from-white dark:to-slate-300 animate-fade-in",
|
| 312 |
+
),
|
| 313 |
+
P(
|
| 314 |
+
"See how Vespa and ColPali can be used for Visual RAG in this demo",
|
| 315 |
+
cls="text-base md:text-2xl text-muted-foreground md:tracking-wide",
|
| 316 |
+
),
|
| 317 |
+
cls="grid gap-5 text-center",
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
def Home():
|
| 322 |
+
return Div(
|
| 323 |
+
Div(
|
| 324 |
+
Hero(),
|
| 325 |
+
SearchBox(with_border=True),
|
| 326 |
+
SampleQueries(),
|
| 327 |
+
ShareButtons(),
|
| 328 |
+
cls="grid gap-8 content-start mt-[13vh]",
|
| 329 |
+
),
|
| 330 |
+
cls="grid w-full h-full max-w-screen-md gap-4 mx-auto",
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def LinkResource(text, href):
|
| 335 |
+
return Li(
|
| 336 |
+
A(
|
| 337 |
+
Lucide(icon="external-link", size="18"),
|
| 338 |
+
text,
|
| 339 |
+
href=href,
|
| 340 |
+
target="_blank",
|
| 341 |
+
cls="flex items-center gap-1.5 hover:underline bold text-md",
|
| 342 |
+
),
|
| 343 |
+
)
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
def AboutThisDemo():
|
| 347 |
+
resources = [
|
| 348 |
+
{
|
| 349 |
+
"text": "Vespa Blog: How we built this demo",
|
| 350 |
+
"href": "https://blog.vespa.ai/visual-rag-in-practice",
|
| 351 |
+
},
|
| 352 |
+
{
|
| 353 |
+
"text": "Notebook to set up Vespa application and feed dataset",
|
| 354 |
+
"href": "https://pyvespa.readthedocs.io/en/latest/examples/visual_pdf_rag_with_vespa_colpali_cloud.html",
|
| 355 |
+
},
|
| 356 |
+
{
|
| 357 |
+
"text": "Web App (FastHTML) Code",
|
| 358 |
+
"href": "https://github.com/vespa-engine/sample-apps/tree/master/visual-retrieval-colpali",
|
| 359 |
+
},
|
| 360 |
+
{
|
| 361 |
+
"text": "Vespa Blog: Scaling ColPali to Billions",
|
| 362 |
+
"href": "https://blog.vespa.ai/scaling-colpali-to-billions/",
|
| 363 |
+
},
|
| 364 |
+
{
|
| 365 |
+
"text": "Vespa Blog: Retrieval with Vision Language Models",
|
| 366 |
+
"href": "https://blog.vespa.ai/retrieval-with-vision-language-models-colpali/",
|
| 367 |
+
},
|
| 368 |
+
]
|
| 369 |
+
return Div(
|
| 370 |
+
H1(
|
| 371 |
+
"About This Demo",
|
| 372 |
+
cls="text-3xl md:text-5xl font-bold tracking-wide md:tracking-wider",
|
| 373 |
+
),
|
| 374 |
+
P(
|
| 375 |
+
"This demo showcases a Visual Retrieval-Augmented Generation (RAG) application over PDFs using ColPali embeddings in Vespa, built entirely in Python, using FastHTML. The code is fully open source.",
|
| 376 |
+
cls="text-base",
|
| 377 |
+
),
|
| 378 |
+
Img(
|
| 379 |
+
src="/static/img/colpali_child.png",
|
| 380 |
+
alt="Example of token level similarity map",
|
| 381 |
+
cls="w-full",
|
| 382 |
+
),
|
| 383 |
+
H2("Resources", cls="text-2xl font-semibold"),
|
| 384 |
+
Ul(
|
| 385 |
+
*[
|
| 386 |
+
LinkResource(resource["text"], resource["href"])
|
| 387 |
+
for resource in resources
|
| 388 |
+
],
|
| 389 |
+
cls="space-y-2 list-disc pl-5",
|
| 390 |
+
),
|
| 391 |
+
H2("Architecture Overview", cls="text-2xl font-semibold"),
|
| 392 |
+
Img(
|
| 393 |
+
src="/static/img/visual-retrieval-demoapp-arch.png",
|
| 394 |
+
alt="Architecture Overview",
|
| 395 |
+
cls="w-full",
|
| 396 |
+
),
|
| 397 |
+
Ul(
|
| 398 |
+
Li(
|
| 399 |
+
Strong("Vespa Application: "),
|
| 400 |
+
"Vespa Application that handles indexing, search, ranking and queries, leveraging features like phased ranking and multivector MaxSim calculations.",
|
| 401 |
+
),
|
| 402 |
+
Li(
|
| 403 |
+
Strong("Frontend: "),
|
| 404 |
+
"Built with FastHTML, offering a professional and responsive user interface without the complexity of separate frontend frameworks.",
|
| 405 |
+
),
|
| 406 |
+
Li(
|
| 407 |
+
Strong("Backend: "),
|
| 408 |
+
"Also built with FastHTML. Handles query embedding inference using ColPali, serves static files, and is responsible for orchestrating interactions between Vespa and the frontend.",
|
| 409 |
+
),
|
| 410 |
+
Li(
|
| 411 |
+
Strong("Gemini API: "),
|
| 412 |
+
"VLM for the AI response, providing responses based on the top results from Vespa.",
|
| 413 |
+
cls="list-disc list-inside",
|
| 414 |
+
),
|
| 415 |
+
H2("User Experience Highlights", cls="text-2xl font-semibold"),
|
| 416 |
+
Ul(
|
| 417 |
+
Li(
|
| 418 |
+
Strong("Fast and Responsive: "),
|
| 419 |
+
"Optimized for quick loading times, with phased content delivery to display essential information immediately while loading detailed data in the background.",
|
| 420 |
+
),
|
| 421 |
+
Li(
|
| 422 |
+
Strong("Similarity Maps: "),
|
| 423 |
+
"Provides visual highlights of the most relevant parts of a page in response to a query, enhancing interpretability.",
|
| 424 |
+
),
|
| 425 |
+
Li(
|
| 426 |
+
Strong("Type-Ahead Suggestions: "),
|
| 427 |
+
"Offers query suggestions to assist users in formulating effective searches.",
|
| 428 |
+
),
|
| 429 |
+
cls="list-disc list-inside",
|
| 430 |
+
),
|
| 431 |
+
cls="grid gap-5",
|
| 432 |
+
),
|
| 433 |
+
H2("Dataset", cls="text-2xl font-semibold"),
|
| 434 |
+
P(
|
| 435 |
+
"The dataset used in this demo is retrieved from reports published by the Norwegian Government Pension Fund Global. It contains 6,992 pages from 116 PDF reports (2000–2024). The information is often presented in visual formats, making it an ideal dataset for visual retrieval applications.",
|
| 436 |
+
cls="text-base",
|
| 437 |
+
),
|
| 438 |
+
Iframe(
|
| 439 |
+
src="https://huggingface.co/datasets/vespa-engine/gpfg-QA/embed/viewer",
|
| 440 |
+
frameborder="0",
|
| 441 |
+
width="100%",
|
| 442 |
+
height="500",
|
| 443 |
+
),
|
| 444 |
+
Hr(), # To add some margin to bottom. Probably a much better way to do this, but the mb-[16vh] class doesn't seem to be applied
|
| 445 |
+
cls="w-full h-full max-w-screen-md gap-4 mx-auto mt-[8vh] mb-[16vh] grid gap-8 content-start",
|
| 446 |
+
)
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
def Search(request, search_results=[]):
|
| 450 |
+
query_value = request.query_params.get("query", "").strip()
|
| 451 |
+
ranking_value = request.query_params.get("ranking", "hybrid")
|
| 452 |
+
return Div(
|
| 453 |
+
Div(
|
| 454 |
+
Div(
|
| 455 |
+
SearchBox(query_value=query_value, ranking_value=ranking_value),
|
| 456 |
+
Div(
|
| 457 |
+
LoadingMessage(),
|
| 458 |
+
id="search-results", # This will be replaced by the search results
|
| 459 |
+
),
|
| 460 |
+
cls="grid",
|
| 461 |
+
),
|
| 462 |
+
cls="grid",
|
| 463 |
+
),
|
| 464 |
+
)
|
| 465 |
+
|
| 466 |
+
|
| 467 |
+
def LoadingMessage(display_text="Retrieving search results"):
|
| 468 |
+
return Div(
|
| 469 |
+
Lucide(icon="loader-circle", cls="size-5 mr-1.5 animate-spin"),
|
| 470 |
+
Span(display_text, cls="text-base text-center"),
|
| 471 |
+
cls="p-10 text-muted-foreground flex items-center justify-center",
|
| 472 |
+
id="loading-indicator",
|
| 473 |
+
)
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
def LoadingSkeleton():
|
| 477 |
+
return Div(
|
| 478 |
+
Div(cls="h-5 bg-muted"),
|
| 479 |
+
Div(cls="h-5 bg-muted"),
|
| 480 |
+
Div(cls="h-5 bg-muted"),
|
| 481 |
+
cls="grid gap-2 animate-pulse",
|
| 482 |
+
)
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
def SimMapButtonReady(query_id, idx, token, token_idx, img_src):
|
| 486 |
+
return Button(
|
| 487 |
+
token.replace("\u2581", ""),
|
| 488 |
+
size="sm",
|
| 489 |
+
data_image_src=img_src,
|
| 490 |
+
id=f"sim-map-button-{query_id}-{idx}-{token_idx}-{token}",
|
| 491 |
+
cls="sim-map-button pointer-events-auto font-mono text-xs h-5 rounded-none px-2",
|
| 492 |
+
)
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
def SimMapButtonPoll(query_id, idx, token, token_idx):
|
| 496 |
+
return Button(
|
| 497 |
+
Lucide(icon="loader-circle", size="15", cls="animate-spin"),
|
| 498 |
+
size="sm",
|
| 499 |
+
disabled=True,
|
| 500 |
+
hx_get=f"/get_sim_map?query_id={query_id}&idx={idx}&token={token}&token_idx={token_idx}",
|
| 501 |
+
hx_trigger="every 0.5s",
|
| 502 |
+
hx_swap="outerHTML",
|
| 503 |
+
cls="pointer-events-auto text-xs h-5 rounded-none px-2",
|
| 504 |
+
)
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
def SearchInfo(search_time, total_count):
|
| 508 |
+
return (
|
| 509 |
+
Div(
|
| 510 |
+
Span(
|
| 511 |
+
"Retrieved ",
|
| 512 |
+
Strong(total_count),
|
| 513 |
+
Span(" results"),
|
| 514 |
+
Span(" in "),
|
| 515 |
+
Strong(f"{search_time:.3f}"), # 3 significant digits
|
| 516 |
+
Span(" seconds."),
|
| 517 |
+
),
|
| 518 |
+
cls="grid bg-background border-t text-sm text-center p-3",
|
| 519 |
+
),
|
| 520 |
+
)
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
def SearchResult(
|
| 524 |
+
results: list,
|
| 525 |
+
query: str,
|
| 526 |
+
query_id: Optional[str] = None,
|
| 527 |
+
search_time: float = 0,
|
| 528 |
+
total_count: int = 0,
|
| 529 |
+
):
|
| 530 |
+
if not results:
|
| 531 |
+
return Div(
|
| 532 |
+
P(
|
| 533 |
+
"No results found for your query.",
|
| 534 |
+
cls="text-muted-foreground text-base text-center",
|
| 535 |
+
),
|
| 536 |
+
cls="grid p-10",
|
| 537 |
+
)
|
| 538 |
+
|
| 539 |
+
doc_ids = []
|
| 540 |
+
# Otherwise, display the search results
|
| 541 |
+
result_items = []
|
| 542 |
+
for idx, result in enumerate(results):
|
| 543 |
+
fields = result["fields"] # Extract the 'fields' part of each result
|
| 544 |
+
doc_id = fields["id"]
|
| 545 |
+
doc_ids.append(doc_id)
|
| 546 |
+
blur_image_base64 = f"data:image/jpeg;base64,{fields['blur_image']}"
|
| 547 |
+
|
| 548 |
+
sim_map_fields = {
|
| 549 |
+
key: value
|
| 550 |
+
for key, value in fields.items()
|
| 551 |
+
if key.startswith(
|
| 552 |
+
"sim_map_"
|
| 553 |
+
) # filtering is done before creating with 'should_filter_token'-function
|
| 554 |
+
}
|
| 555 |
+
|
| 556 |
+
# Generate buttons for the sim_map fields
|
| 557 |
+
sim_map_buttons = []
|
| 558 |
+
for key, value in sim_map_fields.items():
|
| 559 |
+
token = key.split("_")[-2]
|
| 560 |
+
token_idx = int(key.split("_")[-1])
|
| 561 |
+
if value is not None:
|
| 562 |
+
sim_map_base64 = f"data:image/jpeg;base64,{value}"
|
| 563 |
+
sim_map_buttons.append(
|
| 564 |
+
SimMapButtonReady(
|
| 565 |
+
query_id=query_id,
|
| 566 |
+
idx=idx,
|
| 567 |
+
token=token,
|
| 568 |
+
token_idx=token_idx,
|
| 569 |
+
img_src=sim_map_base64,
|
| 570 |
+
)
|
| 571 |
+
)
|
| 572 |
+
else:
|
| 573 |
+
sim_map_buttons.append(
|
| 574 |
+
SimMapButtonPoll(
|
| 575 |
+
query_id=query_id,
|
| 576 |
+
idx=idx,
|
| 577 |
+
token=token,
|
| 578 |
+
token_idx=token_idx,
|
| 579 |
+
)
|
| 580 |
+
)
|
| 581 |
+
|
| 582 |
+
# Add "Reset Image" button to restore the full image
|
| 583 |
+
reset_button = Button(
|
| 584 |
+
"Reset",
|
| 585 |
+
variant="outline",
|
| 586 |
+
size="sm",
|
| 587 |
+
data_image_src=blur_image_base64,
|
| 588 |
+
cls="reset-button pointer-events-auto font-mono text-xs h-5 rounded-none px-2",
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
tokens_icon = Lucide(icon="images", size="15")
|
| 592 |
+
|
| 593 |
+
# Add "Tokens" button - this has no action, just a placeholder
|
| 594 |
+
tokens_button = Button(
|
| 595 |
+
tokens_icon,
|
| 596 |
+
"Tokens",
|
| 597 |
+
size="sm",
|
| 598 |
+
cls="tokens-button flex gap-[3px] font-bold pointer-events-none font-mono text-xs h-5 rounded-none px-2",
|
| 599 |
+
)
|
| 600 |
+
|
| 601 |
+
result_items.append(
|
| 602 |
+
Div(
|
| 603 |
+
Div(
|
| 604 |
+
Div(
|
| 605 |
+
Lucide(icon="file-text"),
|
| 606 |
+
H2(fields["title"], cls="text-xl md:text-2xl font-semibold"),
|
| 607 |
+
Separator(orientation="vertical"),
|
| 608 |
+
Badge(
|
| 609 |
+
f"Relevance score: {result['relevance']:.4f}",
|
| 610 |
+
cls="flex gap-1.5 items-center justify-center",
|
| 611 |
+
),
|
| 612 |
+
cls="flex items-center gap-2",
|
| 613 |
+
),
|
| 614 |
+
Div(
|
| 615 |
+
Button(
|
| 616 |
+
"Hide Text",
|
| 617 |
+
size="sm",
|
| 618 |
+
id=f"toggle-button-{idx}",
|
| 619 |
+
onclick=f"toggleTextContent({idx})",
|
| 620 |
+
cls="hidden md:block",
|
| 621 |
+
),
|
| 622 |
+
),
|
| 623 |
+
cls="flex flex-wrap items-center justify-between bg-background px-3 py-4",
|
| 624 |
+
),
|
| 625 |
+
Div(
|
| 626 |
+
Div(
|
| 627 |
+
Div(
|
| 628 |
+
tokens_button,
|
| 629 |
+
*sim_map_buttons,
|
| 630 |
+
reset_button,
|
| 631 |
+
cls="flex flex-wrap gap-px w-full pointer-events-none",
|
| 632 |
+
),
|
| 633 |
+
Div(
|
| 634 |
+
Div(
|
| 635 |
+
Div(
|
| 636 |
+
Img(
|
| 637 |
+
src=blur_image_base64,
|
| 638 |
+
hx_get=f"/full_image?doc_id={doc_id}",
|
| 639 |
+
style="backdrop-filter: blur(5px);",
|
| 640 |
+
hx_trigger="load",
|
| 641 |
+
hx_swap="outerHTML",
|
| 642 |
+
alt=fields["title"],
|
| 643 |
+
cls="result-image w-full h-full object-contain",
|
| 644 |
+
),
|
| 645 |
+
Div(
|
| 646 |
+
cls="overlay-container absolute top-0 left-0 w-full h-full pointer-events-none"
|
| 647 |
+
),
|
| 648 |
+
cls="relative w-full h-full",
|
| 649 |
+
),
|
| 650 |
+
cls="grid bg-muted p-2",
|
| 651 |
+
),
|
| 652 |
+
cls="block",
|
| 653 |
+
),
|
| 654 |
+
id=f"image-column-{idx}",
|
| 655 |
+
cls="image-column relative bg-background px-3 py-5 grid-image-column",
|
| 656 |
+
),
|
| 657 |
+
Div(
|
| 658 |
+
Div(
|
| 659 |
+
A(
|
| 660 |
+
Lucide(icon="external-link", size="18"),
|
| 661 |
+
f"PDF Source (Page {fields['page_number'] + 1})",
|
| 662 |
+
href=f"{fields['url']}#page={fields['page_number'] + 1}",
|
| 663 |
+
target="_blank",
|
| 664 |
+
cls="flex items-center gap-1.5 font-mono bold text-sm",
|
| 665 |
+
),
|
| 666 |
+
cls="flex items-center justify-end",
|
| 667 |
+
),
|
| 668 |
+
Div(
|
| 669 |
+
Div(
|
| 670 |
+
Div(
|
| 671 |
+
Div(
|
| 672 |
+
Div(
|
| 673 |
+
H3(
|
| 674 |
+
"Dynamic summary",
|
| 675 |
+
cls="text-base font-semibold",
|
| 676 |
+
),
|
| 677 |
+
P(
|
| 678 |
+
NotStr(fields.get("snippet", "")),
|
| 679 |
+
cls="text-highlight text-muted-foreground",
|
| 680 |
+
),
|
| 681 |
+
cls="grid grid-rows-[auto_0px] content-start gap-y-3",
|
| 682 |
+
),
|
| 683 |
+
id=f"result-text-snippet-{idx}",
|
| 684 |
+
cls="grid gap-y-3 p-8 border border-dashed",
|
| 685 |
+
),
|
| 686 |
+
Div(
|
| 687 |
+
Div(
|
| 688 |
+
Div(
|
| 689 |
+
H3(
|
| 690 |
+
"Full text",
|
| 691 |
+
cls="text-base font-semibold",
|
| 692 |
+
),
|
| 693 |
+
Div(
|
| 694 |
+
P(
|
| 695 |
+
NotStr(fields.get("text", "")),
|
| 696 |
+
cls="text-highlight text-muted-foreground",
|
| 697 |
+
),
|
| 698 |
+
Br(),
|
| 699 |
+
),
|
| 700 |
+
cls="grid grid-rows-[auto_0px] content-start gap-y-3",
|
| 701 |
+
),
|
| 702 |
+
id=f"result-text-full-{idx}",
|
| 703 |
+
cls="grid gap-y-3 p-8 border border-dashed",
|
| 704 |
+
),
|
| 705 |
+
Div(
|
| 706 |
+
cls="absolute inset-x-0 bottom-0 bg-gradient-to-t from-[#fcfcfd] dark:from-[#1c2024] pt-[7%]"
|
| 707 |
+
),
|
| 708 |
+
cls="relative grid",
|
| 709 |
+
),
|
| 710 |
+
cls="grid grid-rows-[1fr_1fr] xl:grid-rows-[1fr_2fr] gap-y-8 p-8 text-sm",
|
| 711 |
+
),
|
| 712 |
+
cls="grid bg-background",
|
| 713 |
+
),
|
| 714 |
+
cls="grid bg-muted p-2",
|
| 715 |
+
),
|
| 716 |
+
id=f"text-column-{idx}",
|
| 717 |
+
cls="text-column relative bg-background px-3 py-5 hidden md-grid-text-column",
|
| 718 |
+
),
|
| 719 |
+
id=f"image-text-columns-{idx}",
|
| 720 |
+
cls="relative grid grid-cols-1 border-t grid-image-text-columns",
|
| 721 |
+
),
|
| 722 |
+
cls="grid grid-cols-1 grid-rows-[auto_auto_1fr]",
|
| 723 |
+
),
|
| 724 |
+
)
|
| 725 |
+
|
| 726 |
+
return [
|
| 727 |
+
Div(
|
| 728 |
+
SearchInfo(search_time, total_count),
|
| 729 |
+
*result_items,
|
| 730 |
+
image_swapping,
|
| 731 |
+
toggle_text_content,
|
| 732 |
+
dynamic_elements_scrollbars,
|
| 733 |
+
id="search-results",
|
| 734 |
+
cls="grid grid-cols-1 gap-px bg-border min-h-0",
|
| 735 |
+
),
|
| 736 |
+
Div(
|
| 737 |
+
ChatResult(query_id=query_id, query=query, doc_ids=doc_ids),
|
| 738 |
+
hx_swap_oob="true",
|
| 739 |
+
id="chat_messages",
|
| 740 |
+
),
|
| 741 |
+
]
|
| 742 |
+
|
| 743 |
+
|
| 744 |
+
def ChatResult(query_id: str, query: str, doc_ids: Optional[list] = None):
|
| 745 |
+
messages = Div(LoadingSkeleton())
|
| 746 |
+
|
| 747 |
+
if doc_ids:
|
| 748 |
+
messages = Div(
|
| 749 |
+
LoadingSkeleton(),
|
| 750 |
+
hx_ext="sse",
|
| 751 |
+
sse_connect=f"/get-message?query_id={query_id}&doc_ids={','.join(doc_ids)}&query={quote_plus(query)}",
|
| 752 |
+
sse_swap="message",
|
| 753 |
+
sse_close="close",
|
| 754 |
+
hx_swap="innerHTML",
|
| 755 |
+
)
|
| 756 |
+
|
| 757 |
+
return Div(
|
| 758 |
+
Div("AI-response (Gemini-2.0)", cls="text-xl font-semibold p-5"),
|
| 759 |
+
Div(
|
| 760 |
+
Div(
|
| 761 |
+
messages,
|
| 762 |
+
),
|
| 763 |
+
id="chat-messages",
|
| 764 |
+
cls="overflow-auto min-h-0 grid items-end px-5",
|
| 765 |
+
),
|
| 766 |
+
id="chat_messages",
|
| 767 |
+
cls="h-full grid grid-rows-[auto_1fr_auto] min-h-0 gap-3",
|
| 768 |
+
)
|
src/frontend/layout.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fasthtml.components import Body, Div, Header, Img, Nav, Title
|
| 2 |
+
from fasthtml.xtend import A, Script
|
| 3 |
+
from lucide_fasthtml import Lucide
|
| 4 |
+
from shad4fast import Button, Separator
|
| 5 |
+
|
| 6 |
+
layout_script = Script(
|
| 7 |
+
"""
|
| 8 |
+
document.addEventListener("DOMContentLoaded", function () {
|
| 9 |
+
const main = document.querySelector('main');
|
| 10 |
+
const aside = document.querySelector('aside');
|
| 11 |
+
const body = document.body;
|
| 12 |
+
|
| 13 |
+
if (main && aside && main.nextElementSibling === aside) {
|
| 14 |
+
// If we have both main and aside, adjust the layout for larger screens
|
| 15 |
+
body.classList.remove('grid-cols-1'); // Remove single-column layout
|
| 16 |
+
body.classList.add('md:grid-cols-[minmax(0,_45fr)_minmax(0,_15fr)]'); // Two-column layout on larger screens
|
| 17 |
+
} else if (main) {
|
| 18 |
+
// If only main, keep it full width
|
| 19 |
+
body.classList.add('grid-cols-1');
|
| 20 |
+
}
|
| 21 |
+
});
|
| 22 |
+
"""
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
overlay_scrollbars_manager = Script(
|
| 26 |
+
"""
|
| 27 |
+
(function () {
|
| 28 |
+
const { OverlayScrollbars } = OverlayScrollbarsGlobal;
|
| 29 |
+
|
| 30 |
+
function getPreferredTheme() {
|
| 31 |
+
return localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
| 32 |
+
? 'dark'
|
| 33 |
+
: 'light';
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
function applyOverlayScrollbars(element, scrollbarTheme) {
|
| 37 |
+
// Destroy existing OverlayScrollbars instance if it exists
|
| 38 |
+
const instance = OverlayScrollbars(element);
|
| 39 |
+
if (instance) {
|
| 40 |
+
instance.destroy();
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
// Reinitialize OverlayScrollbars with the correct theme and settings
|
| 44 |
+
OverlayScrollbars(element, {
|
| 45 |
+
overflow: {
|
| 46 |
+
x: 'hidden',
|
| 47 |
+
y: 'scroll'
|
| 48 |
+
},
|
| 49 |
+
scrollbars: {
|
| 50 |
+
theme: scrollbarTheme,
|
| 51 |
+
visibility: 'auto',
|
| 52 |
+
autoHide: 'leave',
|
| 53 |
+
autoHideDelay: 800
|
| 54 |
+
}
|
| 55 |
+
});
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
// Function to get the current scrollbar theme (light or dark)
|
| 59 |
+
function getScrollbarTheme() {
|
| 60 |
+
const isDarkMode = getPreferredTheme() === 'dark';
|
| 61 |
+
return isDarkMode ? 'os-theme-light' : 'os-theme-dark'; // Light theme in dark mode, dark theme in light mode
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
// Expose the common functions globally for reuse
|
| 65 |
+
window.OverlayScrollbarsManager = {
|
| 66 |
+
applyOverlayScrollbars: applyOverlayScrollbars,
|
| 67 |
+
getScrollbarTheme: getScrollbarTheme
|
| 68 |
+
};
|
| 69 |
+
})();
|
| 70 |
+
"""
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
static_elements_scrollbars = Script(
|
| 74 |
+
"""
|
| 75 |
+
(function () {
|
| 76 |
+
const { applyOverlayScrollbars, getScrollbarTheme } = OverlayScrollbarsManager;
|
| 77 |
+
|
| 78 |
+
function applyScrollbarsToStaticElements() {
|
| 79 |
+
const mainElement = document.querySelector('main');
|
| 80 |
+
const chatMessagesElement = document.querySelector('#chat-messages');
|
| 81 |
+
|
| 82 |
+
const scrollbarTheme = getScrollbarTheme();
|
| 83 |
+
|
| 84 |
+
if (mainElement) {
|
| 85 |
+
applyOverlayScrollbars(mainElement, scrollbarTheme);
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
if (chatMessagesElement) {
|
| 89 |
+
applyOverlayScrollbars(chatMessagesElement, scrollbarTheme);
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
// Apply the scrollbars on page load
|
| 94 |
+
applyScrollbarsToStaticElements();
|
| 95 |
+
|
| 96 |
+
// Observe changes in the 'dark' class on the <html> element to adjust the theme dynamically
|
| 97 |
+
const observer = new MutationObserver(applyScrollbarsToStaticElements);
|
| 98 |
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
| 99 |
+
})();
|
| 100 |
+
"""
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def Logo():
|
| 105 |
+
return Div(
|
| 106 |
+
Img(
|
| 107 |
+
src="https://assets.vespa.ai/logos/vespa-logo-black.svg",
|
| 108 |
+
alt="Vespa Logo",
|
| 109 |
+
cls="h-full dark:hidden",
|
| 110 |
+
),
|
| 111 |
+
Img(
|
| 112 |
+
src="https://assets.vespa.ai/logos/vespa-logo-white.svg",
|
| 113 |
+
alt="Vespa Logo Dark Mode",
|
| 114 |
+
cls="h-full hidden dark:block",
|
| 115 |
+
),
|
| 116 |
+
cls="h-[27px]",
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def ThemeToggle(variant="ghost", cls=None, **kwargs):
|
| 121 |
+
return Button(
|
| 122 |
+
Lucide("sun", cls="dark:flex hidden"),
|
| 123 |
+
Lucide("moon", cls="dark:hidden"),
|
| 124 |
+
variant=variant,
|
| 125 |
+
size="icon",
|
| 126 |
+
cls=f"theme-toggle {cls}",
|
| 127 |
+
**kwargs,
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def Links():
|
| 132 |
+
return Nav(
|
| 133 |
+
A(
|
| 134 |
+
Button("About this demo?", variant="link"),
|
| 135 |
+
href="/about-this-demo",
|
| 136 |
+
),
|
| 137 |
+
Separator(orientation="vertical"),
|
| 138 |
+
A(
|
| 139 |
+
Button(Lucide(icon="github"), size="icon", variant="ghost"),
|
| 140 |
+
href="https://github.com/vespa-engine/vespa",
|
| 141 |
+
target="_blank",
|
| 142 |
+
),
|
| 143 |
+
A(
|
| 144 |
+
Button(Lucide(icon="slack"), size="icon", variant="ghost"),
|
| 145 |
+
href="https://slack.vespa.ai",
|
| 146 |
+
target="_blank",
|
| 147 |
+
),
|
| 148 |
+
Separator(orientation="vertical"),
|
| 149 |
+
ThemeToggle(),
|
| 150 |
+
cls="flex items-center space-x-2",
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def Layout(*c, is_home=False, **kwargs):
|
| 155 |
+
return (
|
| 156 |
+
Title("Visual Retrieval ColPali"),
|
| 157 |
+
Body(
|
| 158 |
+
Header(
|
| 159 |
+
A(Logo(), href="/"),
|
| 160 |
+
Links(),
|
| 161 |
+
cls="min-h-[55px] h-[55px] w-full flex items-center justify-between px-4",
|
| 162 |
+
),
|
| 163 |
+
*c,
|
| 164 |
+
**kwargs,
|
| 165 |
+
data_is_home=str(is_home).lower(),
|
| 166 |
+
cls="grid grid-rows-[minmax(0,55px)_minmax(0,1fr)] min-h-0",
|
| 167 |
+
),
|
| 168 |
+
layout_script,
|
| 169 |
+
overlay_scrollbars_manager,
|
| 170 |
+
static_elements_scrollbars,
|
| 171 |
+
)
|
src/globals.css
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@tailwind base;
|
| 2 |
+
@tailwind components;
|
| 3 |
+
@tailwind utilities;
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
@layer base {
|
| 7 |
+
:root {
|
| 8 |
+
--background: 240 20% 99%; /* 1 */
|
| 9 |
+
--foreground: 210 13% 13%; /* 12 */
|
| 10 |
+
--card: 240 20% 99%; /* 1 */
|
| 11 |
+
--card-foreground: 210 13% 13%; /* 12 */
|
| 12 |
+
--popover: 240 20% 99%; /* 1 */
|
| 13 |
+
--popover-foreground: 210 13% 13%; /* 12 */
|
| 14 |
+
--primary: 210 13% 13%; /* 12 */
|
| 15 |
+
--primary-foreground: 240 20% 98%; /* 2 */
|
| 16 |
+
--secondary: 240 11% 95%; /* 3 */
|
| 17 |
+
--secondary-foreground: 210 13% 13%; /* 12 */
|
| 18 |
+
--muted: 240 11% 95%; /* 3 */
|
| 19 |
+
--muted-foreground: 220 6% 40%; /* 11 */
|
| 20 |
+
--accent: 240 11% 95%; /* 3 */
|
| 21 |
+
--accent-foreground: 210 13% 13%; /* 12 */
|
| 22 |
+
--destructive: 358 75% 59%; /* 9 - red */
|
| 23 |
+
--destructive-foreground: 240 20% 98%; /* 2 */
|
| 24 |
+
--border: 240 10% 86%; /* 6 */
|
| 25 |
+
--input: 240 10% 86%; /* 6 */
|
| 26 |
+
--ring: 210 13% 13%; /* 12 */
|
| 27 |
+
--chart-1: 10 78% 54%; /* 9 - tomato */
|
| 28 |
+
--chart-2: 173 80% 36%; /* 9 - teal */
|
| 29 |
+
--chart-3: 206 100% 50%; /* 9 - blue */
|
| 30 |
+
--chart-4: 42 100% 62%; /* 9 - amber */
|
| 31 |
+
--chart-5: 23 93% 53%; /* 9 - orange */
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.dark {
|
| 35 |
+
--background: 240 6% 7%; /* 1 */
|
| 36 |
+
--foreground: 220 9% 94%; /* 12 */
|
| 37 |
+
--card: 240 6% 7%; /* 1 */
|
| 38 |
+
--card-foreground: 220 9% 94%; /* 12 */
|
| 39 |
+
--popover: 240 6% 7%; /* 1 */
|
| 40 |
+
--popover-foreground: 220 9% 94%; /* 12 */
|
| 41 |
+
--primary: 220 9% 94%; /* 12 */
|
| 42 |
+
--primary-foreground: 220 6% 10%; /* 2 */
|
| 43 |
+
--secondary: 225 6% 14%; /* 3 */
|
| 44 |
+
--secondary-foreground: 220 9% 94%; /* 12 */
|
| 45 |
+
--muted: 225 6% 14%; /* 3 */
|
| 46 |
+
--muted-foreground: 216 7% 71%; /* 11 */
|
| 47 |
+
--accent: 225 6% 14%; /* 3 */
|
| 48 |
+
--accent-foreground: 220 9% 94%; /* 12 */
|
| 49 |
+
--destructive: 358 75% 59%; /* 9 - red */
|
| 50 |
+
--destructive-foreground: 220 9% 94%; /* 12 */
|
| 51 |
+
--border: 213 8% 23%; /* 6 */
|
| 52 |
+
--input: 213 8% 23%; /* 6 */
|
| 53 |
+
--ring: 220 9% 94%; /* 12 */
|
| 54 |
+
--chart-1: 10 78% 54%; /* 9 - tomato */
|
| 55 |
+
--chart-2: 173 80% 36%; /* 9 - teal */
|
| 56 |
+
--chart-3: 206 100% 50%; /* 9 - blue */
|
| 57 |
+
--chart-4: 42 100% 62%; /* 9 - amber */
|
| 58 |
+
--chart-5: 23 93% 53%; /* 9 - orange */
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
@layer base {
|
| 63 |
+
:root:has(.no-bg-scroll) {
|
| 64 |
+
overflow: hidden;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
* {
|
| 68 |
+
@apply border-border;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
body {
|
| 72 |
+
@apply bg-background text-foreground antialiased min-h-screen;
|
| 73 |
+
font-feature-settings: "rlig" 1, "calt" 1;
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
@layer utilities {
|
| 78 |
+
|
| 79 |
+
/* Hide scrollbar for Chrome, Safari and Opera */
|
| 80 |
+
.no-scrollbar::-webkit-scrollbar {
|
| 81 |
+
display: none;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
/* Hide scrollbar for IE, Edge and Firefox */
|
| 85 |
+
.no-scrollbar {
|
| 86 |
+
-webkit-overflow-scrolling: touch;
|
| 87 |
+
-ms-overflow-style: none;
|
| 88 |
+
/* IE and Edge */
|
| 89 |
+
scrollbar-width: none;
|
| 90 |
+
/* Firefox */
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
@keyframes slideInFromTop {
|
| 95 |
+
from {
|
| 96 |
+
transform: translateY(-100%);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
to {
|
| 100 |
+
transform: translateY(0);
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
@keyframes slideInFromBottom {
|
| 105 |
+
from {
|
| 106 |
+
transform: translateY(100%);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
to {
|
| 110 |
+
transform: translateY(0);
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
.toast {
|
| 115 |
+
animation-duration: 0.2s;
|
| 116 |
+
animation-fill-mode: forwards;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
@media (max-width: 640px) {
|
| 120 |
+
.toast {
|
| 121 |
+
animation-name: slideInFromTop;
|
| 122 |
+
}
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
@media (min-width: 641px) {
|
| 126 |
+
.toast {
|
| 127 |
+
animation-name: slideInFromBottom;
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
@keyframes fade-in {
|
| 132 |
+
from {
|
| 133 |
+
opacity: 0;
|
| 134 |
+
}
|
| 135 |
+
to {
|
| 136 |
+
opacity: 1;
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
@keyframes slide-up {
|
| 141 |
+
from {
|
| 142 |
+
transform: translateY(20px);
|
| 143 |
+
opacity: 0;
|
| 144 |
+
}
|
| 145 |
+
to {
|
| 146 |
+
transform: translateY(0);
|
| 147 |
+
opacity: 1;
|
| 148 |
+
}
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
.animate-fade-in {
|
| 152 |
+
animation: fade-in 1s ease-out forwards;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.animate-slide-up {
|
| 156 |
+
animation: slide-up 1s ease-out forwards;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
.sim-map-button.active {
|
| 160 |
+
background-color: #61D790;
|
| 161 |
+
color: #2E2F27;
|
| 162 |
+
|
| 163 |
+
&:hover {
|
| 164 |
+
background-color: #61D790;
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.text-highlight strong {
|
| 169 |
+
color: black;
|
| 170 |
+
|
| 171 |
+
.dark & {
|
| 172 |
+
color: white;
|
| 173 |
+
}
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.tokens-button {
|
| 177 |
+
background-color: #B7E2F1;
|
| 178 |
+
color: #2E2F27;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
.overlay-image {
|
| 182 |
+
opacity: 0.5;
|
| 183 |
+
position: absolute;
|
| 184 |
+
top: 0;
|
| 185 |
+
left: 0;
|
| 186 |
+
width: 100%;
|
| 187 |
+
height: 100%;
|
| 188 |
+
z-index: 10;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
header {
|
| 192 |
+
grid-column: 1/-1;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
body {
|
| 196 |
+
&[data-is-home="true"] {
|
| 197 |
+
background: radial-gradient(circle at 50% 100%, #fcfcfd, #fcfcfd, #fdfdfe, #fdfdfe, #fefefe, #fefefe, #ffffff, #ffffff);
|
| 198 |
+
|
| 199 |
+
.dark & {
|
| 200 |
+
background: radial-gradient(circle at 50% 50%, #272a2d, #242629, #212326, #1e1f22, #1b1c1e, #18181b, #151517, #111113);
|
| 201 |
+
}
|
| 202 |
+
}
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
main {
|
| 206 |
+
overflow: auto;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
aside {
|
| 210 |
+
overflow: auto;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
.scroll-container {
|
| 214 |
+
padding-right: 10px;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
.question-message {
|
| 218 |
+
background-color: #61D790;
|
| 219 |
+
color: #2E2F27;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
.grid-image-text-columns {
|
| 223 |
+
@apply md:grid-cols-2 md:col-span-2
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
.grid-image-column {
|
| 227 |
+
@apply grid grid-rows-subgrid row-span-2 content-start;
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
.md-grid-text-column {
|
| 231 |
+
@apply md:grid md:grid-rows-subgrid md:row-span-2 md:content-start;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
#search-input[aria-expanded="true"] {
|
| 235 |
+
border-top: 1px solid hsl(var(--input));
|
| 236 |
+
border-left: 1px solid hsl(var(--input));
|
| 237 |
+
border-right: 1px solid hsl(var(--input));
|
| 238 |
+
border-bottom: none;
|
| 239 |
+
border-bottom-left-radius: 0;
|
| 240 |
+
border-bottom-right-radius: 0;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
.awesomplete {
|
| 244 |
+
width: 100%;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
.awesomplete > ul {
|
| 248 |
+
@apply text-sm space-y-1;
|
| 249 |
+
margin: 0;
|
| 250 |
+
border-top: none;
|
| 251 |
+
border-left: 1px solid hsl(var(--input));
|
| 252 |
+
border-right: 1px solid hsl(var(--input));
|
| 253 |
+
border-bottom: 1px solid hsl(var(--input));
|
| 254 |
+
border-radius: 0 0 calc(var(--radius) - 2px) calc(var(--radius) - 2px);
|
| 255 |
+
background: white;
|
| 256 |
+
|
| 257 |
+
.dark & {
|
| 258 |
+
background: hsl(var(--background));
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
box-shadow: none;
|
| 262 |
+
text-shadow: none;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
.awesomplete > ul:before {
|
| 266 |
+
display: none;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
.awesomplete > ul > li:hover {
|
| 270 |
+
background-color: #B7E2F1;
|
| 271 |
+
color: #2E2F27;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
.awesomplete > ul > li[aria-selected="true"] {
|
| 275 |
+
background-color: #B7E2F1;
|
| 276 |
+
color: #2E2F27;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.awesomplete mark {
|
| 280 |
+
background-color: #61D790;
|
| 281 |
+
color: #2E2F27;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
.awesomplete li:hover mark {
|
| 285 |
+
background-color: #61D790;
|
| 286 |
+
color: #2E2F27;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
.awesomplete li[aria-selected="true"] mark {
|
| 290 |
+
background-color: #61D790;
|
| 291 |
+
color: #2E2F27;
|
| 292 |
+
}
|
| 293 |
+
|
src/icons.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
ICONS = {"chevrons-right": "<path d=\"m6 17 5-5-5-5\"></path><path d=\"m13 17 5-5-5-5\"></path>", "moon": "<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"></path>", "sun": "<circle cx=\"12\" cy=\"12\" r=\"4\"></circle><path d=\"M12 2v2\"></path><path d=\"M12 20v2\"></path><path d=\"m4.93 4.93 1.41 1.41\"></path><path d=\"m17.66 17.66 1.41 1.41\"></path><path d=\"M2 12h2\"></path><path d=\"M20 12h2\"></path><path d=\"m6.34 17.66-1.41 1.41\"></path><path d=\"m19.07 4.93-1.41 1.41\"></path>", "github": "<path d=\"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4\"></path><path d=\"M9 18c-4.51 2-5-2-7-2\"></path>", "slack": "<rect height=\"8\" rx=\"1.5\" width=\"3\" x=\"13\" y=\"2\"></rect><path d=\"M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5\"></path><rect height=\"8\" rx=\"1.5\" width=\"3\" x=\"8\" y=\"14\"></rect><path d=\"M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5\"></path><rect height=\"3\" rx=\"1.5\" width=\"8\" x=\"14\" y=\"13\"></rect><path d=\"M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5\"></path><rect height=\"3\" rx=\"1.5\" width=\"8\" x=\"2\" y=\"8\"></rect><path d=\"M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5\"></path>", "settings": "<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"></path><circle cx=\"12\" cy=\"12\" r=\"3\"></circle>", "arrow-right": "<path d=\"M5 12h14\"></path><path d=\"m12 5 7 7-7 7\"></path>", "search": "<circle cx=\"11\" cy=\"11\" r=\"8\"></circle><path d=\"m21 21-4.3-4.3\"></path>", "file-search": "<path d=\"M14 2v4a2 2 0 0 0 2 2h4\"></path><path d=\"M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3\"></path><path d=\"m9 18-1.5-1.5\"></path><circle cx=\"5\" cy=\"14\" r=\"3\"></circle>", "message-circle-question": "<path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"></path><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"></path><path d=\"M12 17h.01\"></path>", "text-search": "<path d=\"M21 6H3\"></path><path d=\"M10 12H3\"></path><path d=\"M10 18H3\"></path><circle cx=\"17\" cy=\"15\" r=\"3\"></circle><path d=\"m21 19-1.9-1.9\"></path>", "maximize": "<path d=\"M8 3H5a2 2 0 0 0-2 2v3\"></path><path d=\"M21 8V5a2 2 0 0 0-2-2h-3\"></path><path d=\"M3 16v3a2 2 0 0 0 2 2h3\"></path><path d=\"M16 21h3a2 2 0 0 0 2-2v-3\"></path>", "expand": "<path d=\"m21 21-6-6m6 6v-4.8m0 4.8h-4.8\"></path><path d=\"M3 16.2V21m0 0h4.8M3 21l6-6\"></path><path d=\"M21 7.8V3m0 0h-4.8M21 3l-6 6\"></path><path d=\"M3 7.8V3m0 0h4.8M3 3l6 6\"></path>", "fullscreen": "<path d=\"M3 7V5a2 2 0 0 1 2-2h2\"></path><path d=\"M17 3h2a2 2 0 0 1 2 2v2\"></path><path d=\"M21 17v2a2 2 0 0 1-2 2h-2\"></path><path d=\"M7 21H5a2 2 0 0 1-2-2v-2\"></path><rect height=\"8\" rx=\"1\" width=\"10\" x=\"7\" y=\"8\"></rect>", "images": "<path d=\"M18 22H4a2 2 0 0 1-2-2V6\"></path><path d=\"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18\"></path><circle cx=\"12\" cy=\"8\" r=\"2\"></circle><rect height=\"16\" rx=\"2\" width=\"16\" x=\"6\" y=\"2\"></rect>", "circle": "<circle cx=\"12\" cy=\"12\" r=\"10\"></circle>", "loader-circle": "<path d=\"M21 12a9 9 0 1 1-6.219-8.56\"></path>", "file-text": "<path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\"></path><path d=\"M14 2v4a2 2 0 0 0 2 2h4\"></path><path d=\"M10 9H8\"></path><path d=\"M16 13H8\"></path><path d=\"M16 17H8\"></path>", "file-question": "<path d=\"M12 17h.01\"></path><path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z\"></path><path d=\"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3\"></path>", "external-link": "<path d=\"M15 3h6v6\"></path><path d=\"M10 14 21 3\"></path><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path>", "linkedin": "<path d=\"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z\"></path><rect height=\"12\" width=\"4\" x=\"2\" y=\"9\"></rect><circle cx=\"4\" cy=\"4\" r=\"2\"></circle>"}
|
src/main.py
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import base64
|
| 3 |
+
import os
|
| 4 |
+
import time
|
| 5 |
+
import uuid
|
| 6 |
+
import logging
|
| 7 |
+
import sys
|
| 8 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
import google.generativeai as genai
|
| 12 |
+
from fastcore.parallel import threaded
|
| 13 |
+
from fasthtml.common import (
|
| 14 |
+
Aside,
|
| 15 |
+
Div,
|
| 16 |
+
FileResponse,
|
| 17 |
+
HighlightJS,
|
| 18 |
+
Img,
|
| 19 |
+
JSONResponse,
|
| 20 |
+
Link,
|
| 21 |
+
Main,
|
| 22 |
+
P,
|
| 23 |
+
RedirectResponse,
|
| 24 |
+
Script,
|
| 25 |
+
StreamingResponse,
|
| 26 |
+
fast_app,
|
| 27 |
+
serve,
|
| 28 |
+
)
|
| 29 |
+
from PIL import Image
|
| 30 |
+
from shad4fast import ShadHead
|
| 31 |
+
from vespa.application import Vespa
|
| 32 |
+
|
| 33 |
+
from backend.colpali import SimMapGenerator
|
| 34 |
+
from backend.vespa_app import VespaQueryClient
|
| 35 |
+
from frontend.app import (
|
| 36 |
+
AboutThisDemo,
|
| 37 |
+
ChatResult,
|
| 38 |
+
Home,
|
| 39 |
+
Search,
|
| 40 |
+
SearchBox,
|
| 41 |
+
SearchResult,
|
| 42 |
+
SimMapButtonPoll,
|
| 43 |
+
SimMapButtonReady,
|
| 44 |
+
)
|
| 45 |
+
from frontend.layout import Layout
|
| 46 |
+
|
| 47 |
+
highlight_js_theme_link = Link(id="highlight-theme", rel="stylesheet", href="")
|
| 48 |
+
highlight_js_theme = Script(src="/static/js/highlightjs-theme.js")
|
| 49 |
+
highlight_js = HighlightJS(
|
| 50 |
+
langs=["python", "javascript", "java", "json", "xml"],
|
| 51 |
+
dark="github-dark",
|
| 52 |
+
light="github",
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
overlayscrollbars_link = Link(
|
| 56 |
+
rel="stylesheet",
|
| 57 |
+
href="https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/2.10.0/styles/overlayscrollbars.min.css",
|
| 58 |
+
type="text/css",
|
| 59 |
+
)
|
| 60 |
+
overlayscrollbars_js = Script(
|
| 61 |
+
src="https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/2.10.0/browser/overlayscrollbars.browser.es5.min.js"
|
| 62 |
+
)
|
| 63 |
+
awesomplete_link = Link(
|
| 64 |
+
rel="stylesheet",
|
| 65 |
+
href="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.7/awesomplete.min.css",
|
| 66 |
+
type="text/css",
|
| 67 |
+
)
|
| 68 |
+
awesomplete_js = Script(
|
| 69 |
+
src="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.7/awesomplete.min.js"
|
| 70 |
+
)
|
| 71 |
+
sselink = Script(src="https://unpkg.com/htmx-ext-sse@2.2.1/sse.js")
|
| 72 |
+
|
| 73 |
+
# Get log level from environment variable, default to INFO
|
| 74 |
+
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
|
| 75 |
+
# Configure logger
|
| 76 |
+
logger = logging.getLogger("vespa_app")
|
| 77 |
+
handler = logging.StreamHandler(sys.stdout)
|
| 78 |
+
handler.setFormatter(
|
| 79 |
+
logging.Formatter(
|
| 80 |
+
"%(levelname)s: \t %(asctime)s \t %(message)s",
|
| 81 |
+
datefmt="%Y-%m-%d %H:%M:%S",
|
| 82 |
+
)
|
| 83 |
+
)
|
| 84 |
+
logger.addHandler(handler)
|
| 85 |
+
logger.setLevel(getattr(logging, LOG_LEVEL))
|
| 86 |
+
|
| 87 |
+
app, rt = fast_app(
|
| 88 |
+
htmlkw={"cls": "grid h-full"},
|
| 89 |
+
pico=False,
|
| 90 |
+
hdrs=(
|
| 91 |
+
highlight_js,
|
| 92 |
+
highlight_js_theme_link,
|
| 93 |
+
highlight_js_theme,
|
| 94 |
+
overlayscrollbars_link,
|
| 95 |
+
overlayscrollbars_js,
|
| 96 |
+
awesomplete_link,
|
| 97 |
+
awesomplete_js,
|
| 98 |
+
sselink,
|
| 99 |
+
ShadHead(tw_cdn=False, theme_handle=True),
|
| 100 |
+
),
|
| 101 |
+
)
|
| 102 |
+
vespa_app: Vespa = VespaQueryClient(logger=logger)
|
| 103 |
+
thread_pool = ThreadPoolExecutor()
|
| 104 |
+
# Gemini config
|
| 105 |
+
|
| 106 |
+
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
| 107 |
+
GEMINI_SYSTEM_PROMPT = """If the user query is a question, try your best to answer it based on the provided images.
|
| 108 |
+
If the user query can not be interpreted as a question, or if the answer to the query can not be inferred from the images,
|
| 109 |
+
answer with the exact phrase "I am sorry, I can't find enough relevant information on these pages to answer your question.".
|
| 110 |
+
Your response should be HTML formatted, but only simple tags, such as <b>. <p>, <i>, <br> <ul> and <li> are allowed. No HTML tables.
|
| 111 |
+
This means that newlines will be replaced with <br> tags, bold text will be enclosed in <b> tags, and so on.
|
| 112 |
+
Do NOT include backticks (`) in your response. Only simple HTML tags and text.
|
| 113 |
+
"""
|
| 114 |
+
gemini_model = genai.GenerativeModel(
|
| 115 |
+
"gemini-2.0-flash", system_instruction=GEMINI_SYSTEM_PROMPT
|
| 116 |
+
)
|
| 117 |
+
STATIC_DIR = Path("static")
|
| 118 |
+
IMG_DIR = STATIC_DIR / "full_images"
|
| 119 |
+
SIM_MAP_DIR = STATIC_DIR / "sim_maps"
|
| 120 |
+
os.makedirs(IMG_DIR, exist_ok=True)
|
| 121 |
+
os.makedirs(SIM_MAP_DIR, exist_ok=True)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
@app.on_event("startup")
|
| 125 |
+
def load_model_on_startup():
|
| 126 |
+
app.sim_map_generator = SimMapGenerator(logger=logger)
|
| 127 |
+
return
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
@app.on_event("startup")
|
| 131 |
+
async def keepalive():
|
| 132 |
+
asyncio.create_task(poll_vespa_keepalive())
|
| 133 |
+
return
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def generate_query_id(query, ranking_value):
|
| 137 |
+
hash_input = (query + ranking_value).encode("utf-8")
|
| 138 |
+
return hash(hash_input)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
@rt("/static/{filepath:path}")
|
| 142 |
+
def serve_static(filepath: str):
|
| 143 |
+
return FileResponse(STATIC_DIR / filepath)
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
@rt("/")
|
| 147 |
+
def get(session):
|
| 148 |
+
if "session_id" not in session:
|
| 149 |
+
session["session_id"] = str(uuid.uuid4())
|
| 150 |
+
return Layout(Main(Home()), is_home=True)
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
@rt("/about-this-demo")
|
| 154 |
+
def get():
|
| 155 |
+
return Layout(Main(AboutThisDemo()))
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
@rt("/search")
|
| 159 |
+
def get(request, query: str = "", ranking: str = "hybrid"):
|
| 160 |
+
logger.info(f"/search: Fetching results for query: {query}, ranking: {ranking}")
|
| 161 |
+
|
| 162 |
+
# Always render the SearchBox first
|
| 163 |
+
if not query:
|
| 164 |
+
# Show SearchBox and a message for missing query
|
| 165 |
+
return Layout(
|
| 166 |
+
Main(
|
| 167 |
+
Div(
|
| 168 |
+
SearchBox(query_value=query, ranking_value=ranking),
|
| 169 |
+
Div(
|
| 170 |
+
P(
|
| 171 |
+
"No query provided. Please enter a query.",
|
| 172 |
+
cls="text-center text-muted-foreground",
|
| 173 |
+
),
|
| 174 |
+
cls="p-10",
|
| 175 |
+
),
|
| 176 |
+
cls="grid",
|
| 177 |
+
)
|
| 178 |
+
)
|
| 179 |
+
)
|
| 180 |
+
# Generate a unique query_id based on the query and ranking value
|
| 181 |
+
query_id = generate_query_id(query, ranking)
|
| 182 |
+
# Show the loading message if a query is provided
|
| 183 |
+
return Layout(
|
| 184 |
+
Main(Search(request), data_overlayscrollbars_initialize=True, cls="border-t"),
|
| 185 |
+
Aside(
|
| 186 |
+
ChatResult(query_id=query_id, query=query),
|
| 187 |
+
cls="border-t border-l hidden md:block",
|
| 188 |
+
),
|
| 189 |
+
) # Show SearchBox and Loading message initially
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
@rt("/fetch_results")
|
| 193 |
+
async def get(session, request, query: str, ranking: str):
|
| 194 |
+
if "hx-request" not in request.headers:
|
| 195 |
+
return RedirectResponse("/search")
|
| 196 |
+
|
| 197 |
+
# Get the hash of the query and ranking value
|
| 198 |
+
query_id = generate_query_id(query, ranking)
|
| 199 |
+
logger.info(f"Query id in /fetch_results: {query_id}")
|
| 200 |
+
# Run the embedding and query against Vespa app
|
| 201 |
+
start_inference = time.perf_counter()
|
| 202 |
+
q_embs, idx_to_token = app.sim_map_generator.get_query_embeddings_and_token_map(
|
| 203 |
+
query
|
| 204 |
+
)
|
| 205 |
+
end_inference = time.perf_counter()
|
| 206 |
+
logger.info(
|
| 207 |
+
f"Inference time for query_id: {query_id} \t {end_inference - start_inference:.2f} seconds"
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
start = time.perf_counter()
|
| 211 |
+
# Fetch real search results from Vespa
|
| 212 |
+
result = await vespa_app.get_result_from_query(
|
| 213 |
+
query=query,
|
| 214 |
+
q_embs=q_embs,
|
| 215 |
+
ranking=ranking,
|
| 216 |
+
idx_to_token=idx_to_token,
|
| 217 |
+
)
|
| 218 |
+
end = time.perf_counter()
|
| 219 |
+
logger.info(
|
| 220 |
+
f"Search results fetched in {end - start:.2f} seconds. Vespa search time: {result['timing']['searchtime']}"
|
| 221 |
+
)
|
| 222 |
+
search_time = result["timing"]["searchtime"]
|
| 223 |
+
# Safely get total_count with a default of 0
|
| 224 |
+
total_count = result.get("root", {}).get("fields", {}).get("totalCount", 0)
|
| 225 |
+
|
| 226 |
+
search_results = vespa_app.results_to_search_results(result, idx_to_token)
|
| 227 |
+
|
| 228 |
+
get_and_store_sim_maps(
|
| 229 |
+
query_id=query_id,
|
| 230 |
+
query=query,
|
| 231 |
+
q_embs=q_embs,
|
| 232 |
+
ranking=ranking,
|
| 233 |
+
idx_to_token=idx_to_token,
|
| 234 |
+
doc_ids=[result["fields"]["id"] for result in search_results],
|
| 235 |
+
)
|
| 236 |
+
return SearchResult(search_results, query, query_id, search_time, total_count)
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def get_results_children(result):
|
| 240 |
+
search_results = (
|
| 241 |
+
result["root"]["children"]
|
| 242 |
+
if "root" in result and "children" in result["root"]
|
| 243 |
+
else []
|
| 244 |
+
)
|
| 245 |
+
return search_results
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
async def poll_vespa_keepalive():
|
| 249 |
+
while True:
|
| 250 |
+
await asyncio.sleep(5)
|
| 251 |
+
await vespa_app.keepalive()
|
| 252 |
+
logger.debug(f"Vespa keepalive: {time.time()}")
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
@threaded
|
| 256 |
+
def get_and_store_sim_maps(
|
| 257 |
+
query_id, query: str, q_embs, ranking, idx_to_token, doc_ids
|
| 258 |
+
):
|
| 259 |
+
ranking_sim = ranking + "_sim"
|
| 260 |
+
vespa_sim_maps = vespa_app.get_sim_maps_from_query(
|
| 261 |
+
query=query,
|
| 262 |
+
q_embs=q_embs,
|
| 263 |
+
ranking=ranking_sim,
|
| 264 |
+
idx_to_token=idx_to_token,
|
| 265 |
+
)
|
| 266 |
+
img_paths = [IMG_DIR / f"{doc_id}.jpg" for doc_id in doc_ids]
|
| 267 |
+
# All images should be downloaded, but best to wait 5 secs
|
| 268 |
+
max_wait = 5
|
| 269 |
+
start_time = time.time()
|
| 270 |
+
while (
|
| 271 |
+
not all([os.path.exists(img_path) for img_path in img_paths])
|
| 272 |
+
and time.time() - start_time < max_wait
|
| 273 |
+
):
|
| 274 |
+
time.sleep(0.2)
|
| 275 |
+
if not all([os.path.exists(img_path) for img_path in img_paths]):
|
| 276 |
+
logger.warning(f"Images not ready in 5 seconds for query_id: {query_id}")
|
| 277 |
+
return False
|
| 278 |
+
sim_map_generator = app.sim_map_generator.gen_similarity_maps(
|
| 279 |
+
query=query,
|
| 280 |
+
query_embs=q_embs,
|
| 281 |
+
token_idx_map=idx_to_token,
|
| 282 |
+
images=img_paths,
|
| 283 |
+
vespa_sim_maps=vespa_sim_maps,
|
| 284 |
+
)
|
| 285 |
+
for idx, token, token_idx, blended_img_base64 in sim_map_generator:
|
| 286 |
+
with open(SIM_MAP_DIR / f"{query_id}_{idx}_{token_idx}.png", "wb") as f:
|
| 287 |
+
f.write(base64.b64decode(blended_img_base64))
|
| 288 |
+
logger.debug(
|
| 289 |
+
f"Sim map saved to disk for query_id: {query_id}, idx: {idx}, token: {token}"
|
| 290 |
+
)
|
| 291 |
+
return True
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
@app.get("/get_sim_map")
|
| 295 |
+
async def get_sim_map(query_id: str, idx: int, token: str, token_idx: int):
|
| 296 |
+
"""
|
| 297 |
+
Endpoint that each of the sim map button polls to get the sim map image
|
| 298 |
+
when it is ready. If it is not ready, returns a SimMapButtonPoll, that
|
| 299 |
+
continues to poll every 1 second.
|
| 300 |
+
"""
|
| 301 |
+
sim_map_path = SIM_MAP_DIR / f"{query_id}_{idx}_{token_idx}.png"
|
| 302 |
+
if not os.path.exists(sim_map_path):
|
| 303 |
+
logger.debug(
|
| 304 |
+
f"Sim map not ready for query_id: {query_id}, idx: {idx}, token: {token}"
|
| 305 |
+
)
|
| 306 |
+
return SimMapButtonPoll(
|
| 307 |
+
query_id=query_id, idx=idx, token=token, token_idx=token_idx
|
| 308 |
+
)
|
| 309 |
+
else:
|
| 310 |
+
return SimMapButtonReady(
|
| 311 |
+
query_id=query_id,
|
| 312 |
+
idx=idx,
|
| 313 |
+
token=token,
|
| 314 |
+
token_idx=token_idx,
|
| 315 |
+
img_src=sim_map_path,
|
| 316 |
+
)
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
@app.get("/full_image")
|
| 320 |
+
async def full_image(doc_id: str):
|
| 321 |
+
"""
|
| 322 |
+
Endpoint to get the full quality image for a given result id.
|
| 323 |
+
"""
|
| 324 |
+
img_path = IMG_DIR / f"{doc_id}.jpg"
|
| 325 |
+
if not os.path.exists(img_path):
|
| 326 |
+
image_data = await vespa_app.get_full_image_from_vespa(doc_id)
|
| 327 |
+
# image data is base 64 encoded string. Save it to disk as jpg.
|
| 328 |
+
with open(img_path, "wb") as f:
|
| 329 |
+
f.write(base64.b64decode(image_data))
|
| 330 |
+
logger.debug(f"Full image saved to disk for doc_id: {doc_id}")
|
| 331 |
+
else:
|
| 332 |
+
with open(img_path, "rb") as f:
|
| 333 |
+
image_data = base64.b64encode(f.read()).decode("utf-8")
|
| 334 |
+
return Img(
|
| 335 |
+
src=f"data:image/jpeg;base64,{image_data}",
|
| 336 |
+
alt="something",
|
| 337 |
+
cls="result-image w-full h-full object-contain",
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
@rt("/suggestions")
|
| 342 |
+
async def get_suggestions(query: str = ""):
|
| 343 |
+
"""Endpoint to get suggestions as user types in the search box"""
|
| 344 |
+
query = query.lower().strip()
|
| 345 |
+
|
| 346 |
+
if query:
|
| 347 |
+
suggestions = await vespa_app.get_suggestions(query)
|
| 348 |
+
if len(suggestions) > 0:
|
| 349 |
+
return JSONResponse({"suggestions": suggestions})
|
| 350 |
+
|
| 351 |
+
return JSONResponse({"suggestions": []})
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
async def message_generator(query_id: str, query: str, doc_ids: list):
|
| 355 |
+
"""Generator function to yield SSE messages for chat response"""
|
| 356 |
+
images = []
|
| 357 |
+
num_images = 3 # Number of images before firing chat request
|
| 358 |
+
max_wait = 10 # seconds
|
| 359 |
+
start_time = time.time()
|
| 360 |
+
# Check if full images are ready on disk
|
| 361 |
+
while (
|
| 362 |
+
len(images) < min(num_images, len(doc_ids))
|
| 363 |
+
and time.time() - start_time < max_wait
|
| 364 |
+
):
|
| 365 |
+
images = []
|
| 366 |
+
for idx in range(num_images):
|
| 367 |
+
image_filename = IMG_DIR / f"{doc_ids[idx]}.jpg"
|
| 368 |
+
if not os.path.exists(image_filename):
|
| 369 |
+
logger.debug(
|
| 370 |
+
f"Message generator: Full image not ready for query_id: {query_id}, idx: {idx}"
|
| 371 |
+
)
|
| 372 |
+
continue
|
| 373 |
+
else:
|
| 374 |
+
logger.debug(
|
| 375 |
+
f"Message generator: image ready for query_id: {query_id}, idx: {idx}"
|
| 376 |
+
)
|
| 377 |
+
images.append(Image.open(image_filename))
|
| 378 |
+
if len(images) < num_images:
|
| 379 |
+
await asyncio.sleep(0.2)
|
| 380 |
+
|
| 381 |
+
# yield message with number of images ready
|
| 382 |
+
yield f"event: message\ndata: Generating response based on {len(images)} images...\n\n"
|
| 383 |
+
if not images:
|
| 384 |
+
yield "event: message\ndata: Failed to send images to Gemini 2.0!\n\n"
|
| 385 |
+
yield "event: close\ndata: \n\n"
|
| 386 |
+
return
|
| 387 |
+
|
| 388 |
+
# If newlines are present in the response, the connection will be closed.
|
| 389 |
+
def replace_newline_with_br(text):
|
| 390 |
+
return text.replace("\n", "<br>")
|
| 391 |
+
|
| 392 |
+
response_text = ""
|
| 393 |
+
async for chunk in await gemini_model.generate_content_async(
|
| 394 |
+
images + ["\n\n Query: ", query], stream=True
|
| 395 |
+
):
|
| 396 |
+
if chunk.text:
|
| 397 |
+
response_text += chunk.text
|
| 398 |
+
response_text = replace_newline_with_br(response_text)
|
| 399 |
+
yield f"event: message\ndata: {response_text}\n\n"
|
| 400 |
+
await asyncio.sleep(0.1)
|
| 401 |
+
yield "event: close\ndata: \n\n"
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
@app.get("/get-message")
|
| 405 |
+
async def get_message(query_id: str, query: str, doc_ids: str):
|
| 406 |
+
return StreamingResponse(
|
| 407 |
+
message_generator(query_id=query_id, query=query, doc_ids=doc_ids.split(",")),
|
| 408 |
+
media_type="text/event-stream",
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
@rt("/app")
|
| 413 |
+
def get():
|
| 414 |
+
return Layout(Main(Div(P(f"Connected to Vespa at {vespa_app.url}"), cls="p-4")))
|
| 415 |
+
|
| 416 |
+
|
| 417 |
+
if __name__ == "__main__":
|
| 418 |
+
HOT_RELOAD = os.getenv("HOT_RELOAD", "False").lower() == "true"
|
| 419 |
+
logger.info(f"Starting app with hot reload: {HOT_RELOAD}")
|
| 420 |
+
serve(port=7860, reload=HOT_RELOAD)
|
src/output.css
ADDED
|
@@ -0,0 +1,2973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*, ::before, ::after {
|
| 2 |
+
--tw-border-spacing-x: 0;
|
| 3 |
+
--tw-border-spacing-y: 0;
|
| 4 |
+
--tw-translate-x: 0;
|
| 5 |
+
--tw-translate-y: 0;
|
| 6 |
+
--tw-rotate: 0;
|
| 7 |
+
--tw-skew-x: 0;
|
| 8 |
+
--tw-skew-y: 0;
|
| 9 |
+
--tw-scale-x: 1;
|
| 10 |
+
--tw-scale-y: 1;
|
| 11 |
+
--tw-pan-x: ;
|
| 12 |
+
--tw-pan-y: ;
|
| 13 |
+
--tw-pinch-zoom: ;
|
| 14 |
+
--tw-scroll-snap-strictness: proximity;
|
| 15 |
+
--tw-gradient-from-position: ;
|
| 16 |
+
--tw-gradient-via-position: ;
|
| 17 |
+
--tw-gradient-to-position: ;
|
| 18 |
+
--tw-ordinal: ;
|
| 19 |
+
--tw-slashed-zero: ;
|
| 20 |
+
--tw-numeric-figure: ;
|
| 21 |
+
--tw-numeric-spacing: ;
|
| 22 |
+
--tw-numeric-fraction: ;
|
| 23 |
+
--tw-ring-inset: ;
|
| 24 |
+
--tw-ring-offset-width: 0px;
|
| 25 |
+
--tw-ring-offset-color: #fff;
|
| 26 |
+
--tw-ring-color: rgb(59 130 246 / 0.5);
|
| 27 |
+
--tw-ring-offset-shadow: 0 0 #0000;
|
| 28 |
+
--tw-ring-shadow: 0 0 #0000;
|
| 29 |
+
--tw-shadow: 0 0 #0000;
|
| 30 |
+
--tw-shadow-colored: 0 0 #0000;
|
| 31 |
+
--tw-blur: ;
|
| 32 |
+
--tw-brightness: ;
|
| 33 |
+
--tw-contrast: ;
|
| 34 |
+
--tw-grayscale: ;
|
| 35 |
+
--tw-hue-rotate: ;
|
| 36 |
+
--tw-invert: ;
|
| 37 |
+
--tw-saturate: ;
|
| 38 |
+
--tw-sepia: ;
|
| 39 |
+
--tw-drop-shadow: ;
|
| 40 |
+
--tw-backdrop-blur: ;
|
| 41 |
+
--tw-backdrop-brightness: ;
|
| 42 |
+
--tw-backdrop-contrast: ;
|
| 43 |
+
--tw-backdrop-grayscale: ;
|
| 44 |
+
--tw-backdrop-hue-rotate: ;
|
| 45 |
+
--tw-backdrop-invert: ;
|
| 46 |
+
--tw-backdrop-opacity: ;
|
| 47 |
+
--tw-backdrop-saturate: ;
|
| 48 |
+
--tw-backdrop-sepia: ;
|
| 49 |
+
--tw-contain-size: ;
|
| 50 |
+
--tw-contain-layout: ;
|
| 51 |
+
--tw-contain-paint: ;
|
| 52 |
+
--tw-contain-style: ;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
::backdrop {
|
| 56 |
+
--tw-border-spacing-x: 0;
|
| 57 |
+
--tw-border-spacing-y: 0;
|
| 58 |
+
--tw-translate-x: 0;
|
| 59 |
+
--tw-translate-y: 0;
|
| 60 |
+
--tw-rotate: 0;
|
| 61 |
+
--tw-skew-x: 0;
|
| 62 |
+
--tw-skew-y: 0;
|
| 63 |
+
--tw-scale-x: 1;
|
| 64 |
+
--tw-scale-y: 1;
|
| 65 |
+
--tw-pan-x: ;
|
| 66 |
+
--tw-pan-y: ;
|
| 67 |
+
--tw-pinch-zoom: ;
|
| 68 |
+
--tw-scroll-snap-strictness: proximity;
|
| 69 |
+
--tw-gradient-from-position: ;
|
| 70 |
+
--tw-gradient-via-position: ;
|
| 71 |
+
--tw-gradient-to-position: ;
|
| 72 |
+
--tw-ordinal: ;
|
| 73 |
+
--tw-slashed-zero: ;
|
| 74 |
+
--tw-numeric-figure: ;
|
| 75 |
+
--tw-numeric-spacing: ;
|
| 76 |
+
--tw-numeric-fraction: ;
|
| 77 |
+
--tw-ring-inset: ;
|
| 78 |
+
--tw-ring-offset-width: 0px;
|
| 79 |
+
--tw-ring-offset-color: #fff;
|
| 80 |
+
--tw-ring-color: rgb(59 130 246 / 0.5);
|
| 81 |
+
--tw-ring-offset-shadow: 0 0 #0000;
|
| 82 |
+
--tw-ring-shadow: 0 0 #0000;
|
| 83 |
+
--tw-shadow: 0 0 #0000;
|
| 84 |
+
--tw-shadow-colored: 0 0 #0000;
|
| 85 |
+
--tw-blur: ;
|
| 86 |
+
--tw-brightness: ;
|
| 87 |
+
--tw-contrast: ;
|
| 88 |
+
--tw-grayscale: ;
|
| 89 |
+
--tw-hue-rotate: ;
|
| 90 |
+
--tw-invert: ;
|
| 91 |
+
--tw-saturate: ;
|
| 92 |
+
--tw-sepia: ;
|
| 93 |
+
--tw-drop-shadow: ;
|
| 94 |
+
--tw-backdrop-blur: ;
|
| 95 |
+
--tw-backdrop-brightness: ;
|
| 96 |
+
--tw-backdrop-contrast: ;
|
| 97 |
+
--tw-backdrop-grayscale: ;
|
| 98 |
+
--tw-backdrop-hue-rotate: ;
|
| 99 |
+
--tw-backdrop-invert: ;
|
| 100 |
+
--tw-backdrop-opacity: ;
|
| 101 |
+
--tw-backdrop-saturate: ;
|
| 102 |
+
--tw-backdrop-sepia: ;
|
| 103 |
+
--tw-contain-size: ;
|
| 104 |
+
--tw-contain-layout: ;
|
| 105 |
+
--tw-contain-paint: ;
|
| 106 |
+
--tw-contain-style: ;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
/*
|
| 110 |
+
! tailwindcss v3.4.13 | MIT License | https://tailwindcss.com
|
| 111 |
+
*/
|
| 112 |
+
|
| 113 |
+
/*
|
| 114 |
+
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
| 115 |
+
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
| 116 |
+
*/
|
| 117 |
+
|
| 118 |
+
*,
|
| 119 |
+
::before,
|
| 120 |
+
::after {
|
| 121 |
+
box-sizing: border-box;
|
| 122 |
+
/* 1 */
|
| 123 |
+
border-width: 0;
|
| 124 |
+
/* 2 */
|
| 125 |
+
border-style: solid;
|
| 126 |
+
/* 2 */
|
| 127 |
+
border-color: #e5e7eb;
|
| 128 |
+
/* 2 */
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
::before,
|
| 132 |
+
::after {
|
| 133 |
+
--tw-content: '';
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
/*
|
| 137 |
+
1. Use a consistent sensible line-height in all browsers.
|
| 138 |
+
2. Prevent adjustments of font size after orientation changes in iOS.
|
| 139 |
+
3. Use a more readable tab size.
|
| 140 |
+
4. Use the user's configured `sans` font-family by default.
|
| 141 |
+
5. Use the user's configured `sans` font-feature-settings by default.
|
| 142 |
+
6. Use the user's configured `sans` font-variation-settings by default.
|
| 143 |
+
7. Disable tap highlights on iOS
|
| 144 |
+
*/
|
| 145 |
+
|
| 146 |
+
html,
|
| 147 |
+
:host {
|
| 148 |
+
line-height: 1.5;
|
| 149 |
+
/* 1 */
|
| 150 |
+
-webkit-text-size-adjust: 100%;
|
| 151 |
+
/* 2 */
|
| 152 |
+
-moz-tab-size: 4;
|
| 153 |
+
/* 3 */
|
| 154 |
+
-o-tab-size: 4;
|
| 155 |
+
tab-size: 4;
|
| 156 |
+
/* 3 */
|
| 157 |
+
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
| 158 |
+
/* 4 */
|
| 159 |
+
font-feature-settings: normal;
|
| 160 |
+
/* 5 */
|
| 161 |
+
font-variation-settings: normal;
|
| 162 |
+
/* 6 */
|
| 163 |
+
-webkit-tap-highlight-color: transparent;
|
| 164 |
+
/* 7 */
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
/*
|
| 168 |
+
1. Remove the margin in all browsers.
|
| 169 |
+
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
| 170 |
+
*/
|
| 171 |
+
|
| 172 |
+
body {
|
| 173 |
+
margin: 0;
|
| 174 |
+
/* 1 */
|
| 175 |
+
line-height: inherit;
|
| 176 |
+
/* 2 */
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
/*
|
| 180 |
+
1. Add the correct height in Firefox.
|
| 181 |
+
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
| 182 |
+
3. Ensure horizontal rules are visible by default.
|
| 183 |
+
*/
|
| 184 |
+
|
| 185 |
+
hr {
|
| 186 |
+
height: 0;
|
| 187 |
+
/* 1 */
|
| 188 |
+
color: inherit;
|
| 189 |
+
/* 2 */
|
| 190 |
+
border-top-width: 1px;
|
| 191 |
+
/* 3 */
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
/*
|
| 195 |
+
Add the correct text decoration in Chrome, Edge, and Safari.
|
| 196 |
+
*/
|
| 197 |
+
|
| 198 |
+
abbr:where([title]) {
|
| 199 |
+
-webkit-text-decoration: underline dotted;
|
| 200 |
+
text-decoration: underline dotted;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
/*
|
| 204 |
+
Remove the default font size and weight for headings.
|
| 205 |
+
*/
|
| 206 |
+
|
| 207 |
+
h1,
|
| 208 |
+
h2,
|
| 209 |
+
h3,
|
| 210 |
+
h4,
|
| 211 |
+
h5,
|
| 212 |
+
h6 {
|
| 213 |
+
font-size: inherit;
|
| 214 |
+
font-weight: inherit;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
/*
|
| 218 |
+
Reset links to optimize for opt-in styling instead of opt-out.
|
| 219 |
+
*/
|
| 220 |
+
|
| 221 |
+
a {
|
| 222 |
+
color: inherit;
|
| 223 |
+
text-decoration: inherit;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
/*
|
| 227 |
+
Add the correct font weight in Edge and Safari.
|
| 228 |
+
*/
|
| 229 |
+
|
| 230 |
+
b,
|
| 231 |
+
strong {
|
| 232 |
+
font-weight: bolder;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
/*
|
| 236 |
+
1. Use the user's configured `mono` font-family by default.
|
| 237 |
+
2. Use the user's configured `mono` font-feature-settings by default.
|
| 238 |
+
3. Use the user's configured `mono` font-variation-settings by default.
|
| 239 |
+
4. Correct the odd `em` font sizing in all browsers.
|
| 240 |
+
*/
|
| 241 |
+
|
| 242 |
+
code,
|
| 243 |
+
kbd,
|
| 244 |
+
samp,
|
| 245 |
+
pre {
|
| 246 |
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
| 247 |
+
/* 1 */
|
| 248 |
+
font-feature-settings: normal;
|
| 249 |
+
/* 2 */
|
| 250 |
+
font-variation-settings: normal;
|
| 251 |
+
/* 3 */
|
| 252 |
+
font-size: 1em;
|
| 253 |
+
/* 4 */
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
/*
|
| 257 |
+
Add the correct font size in all browsers.
|
| 258 |
+
*/
|
| 259 |
+
|
| 260 |
+
small {
|
| 261 |
+
font-size: 80%;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
/*
|
| 265 |
+
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
| 266 |
+
*/
|
| 267 |
+
|
| 268 |
+
sub,
|
| 269 |
+
sup {
|
| 270 |
+
font-size: 75%;
|
| 271 |
+
line-height: 0;
|
| 272 |
+
position: relative;
|
| 273 |
+
vertical-align: baseline;
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
sub {
|
| 277 |
+
bottom: -0.25em;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
sup {
|
| 281 |
+
top: -0.5em;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
/*
|
| 285 |
+
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
| 286 |
+
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
| 287 |
+
3. Remove gaps between table borders by default.
|
| 288 |
+
*/
|
| 289 |
+
|
| 290 |
+
table {
|
| 291 |
+
text-indent: 0;
|
| 292 |
+
/* 1 */
|
| 293 |
+
border-color: inherit;
|
| 294 |
+
/* 2 */
|
| 295 |
+
border-collapse: collapse;
|
| 296 |
+
/* 3 */
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
/*
|
| 300 |
+
1. Change the font styles in all browsers.
|
| 301 |
+
2. Remove the margin in Firefox and Safari.
|
| 302 |
+
3. Remove default padding in all browsers.
|
| 303 |
+
*/
|
| 304 |
+
|
| 305 |
+
button,
|
| 306 |
+
input,
|
| 307 |
+
optgroup,
|
| 308 |
+
select,
|
| 309 |
+
textarea {
|
| 310 |
+
font-family: inherit;
|
| 311 |
+
/* 1 */
|
| 312 |
+
font-feature-settings: inherit;
|
| 313 |
+
/* 1 */
|
| 314 |
+
font-variation-settings: inherit;
|
| 315 |
+
/* 1 */
|
| 316 |
+
font-size: 100%;
|
| 317 |
+
/* 1 */
|
| 318 |
+
font-weight: inherit;
|
| 319 |
+
/* 1 */
|
| 320 |
+
line-height: inherit;
|
| 321 |
+
/* 1 */
|
| 322 |
+
letter-spacing: inherit;
|
| 323 |
+
/* 1 */
|
| 324 |
+
color: inherit;
|
| 325 |
+
/* 1 */
|
| 326 |
+
margin: 0;
|
| 327 |
+
/* 2 */
|
| 328 |
+
padding: 0;
|
| 329 |
+
/* 3 */
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
/*
|
| 333 |
+
Remove the inheritance of text transform in Edge and Firefox.
|
| 334 |
+
*/
|
| 335 |
+
|
| 336 |
+
button,
|
| 337 |
+
select {
|
| 338 |
+
text-transform: none;
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
/*
|
| 342 |
+
1. Correct the inability to style clickable types in iOS and Safari.
|
| 343 |
+
2. Remove default button styles.
|
| 344 |
+
*/
|
| 345 |
+
|
| 346 |
+
button,
|
| 347 |
+
input:where([type='button']),
|
| 348 |
+
input:where([type='reset']),
|
| 349 |
+
input:where([type='submit']) {
|
| 350 |
+
-webkit-appearance: button;
|
| 351 |
+
/* 1 */
|
| 352 |
+
background-color: transparent;
|
| 353 |
+
/* 2 */
|
| 354 |
+
background-image: none;
|
| 355 |
+
/* 2 */
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
/*
|
| 359 |
+
Use the modern Firefox focus style for all focusable elements.
|
| 360 |
+
*/
|
| 361 |
+
|
| 362 |
+
:-moz-focusring {
|
| 363 |
+
outline: auto;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
/*
|
| 367 |
+
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
| 368 |
+
*/
|
| 369 |
+
|
| 370 |
+
:-moz-ui-invalid {
|
| 371 |
+
box-shadow: none;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
/*
|
| 375 |
+
Add the correct vertical alignment in Chrome and Firefox.
|
| 376 |
+
*/
|
| 377 |
+
|
| 378 |
+
progress {
|
| 379 |
+
vertical-align: baseline;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
/*
|
| 383 |
+
Correct the cursor style of increment and decrement buttons in Safari.
|
| 384 |
+
*/
|
| 385 |
+
|
| 386 |
+
::-webkit-inner-spin-button,
|
| 387 |
+
::-webkit-outer-spin-button {
|
| 388 |
+
height: auto;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
/*
|
| 392 |
+
1. Correct the odd appearance in Chrome and Safari.
|
| 393 |
+
2. Correct the outline style in Safari.
|
| 394 |
+
*/
|
| 395 |
+
|
| 396 |
+
[type='search'] {
|
| 397 |
+
-webkit-appearance: textfield;
|
| 398 |
+
/* 1 */
|
| 399 |
+
outline-offset: -2px;
|
| 400 |
+
/* 2 */
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
/*
|
| 404 |
+
Remove the inner padding in Chrome and Safari on macOS.
|
| 405 |
+
*/
|
| 406 |
+
|
| 407 |
+
::-webkit-search-decoration {
|
| 408 |
+
-webkit-appearance: none;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
/*
|
| 412 |
+
1. Correct the inability to style clickable types in iOS and Safari.
|
| 413 |
+
2. Change font properties to `inherit` in Safari.
|
| 414 |
+
*/
|
| 415 |
+
|
| 416 |
+
::-webkit-file-upload-button {
|
| 417 |
+
-webkit-appearance: button;
|
| 418 |
+
/* 1 */
|
| 419 |
+
font: inherit;
|
| 420 |
+
/* 2 */
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
/*
|
| 424 |
+
Add the correct display in Chrome and Safari.
|
| 425 |
+
*/
|
| 426 |
+
|
| 427 |
+
summary {
|
| 428 |
+
display: list-item;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
/*
|
| 432 |
+
Removes the default spacing and border for appropriate elements.
|
| 433 |
+
*/
|
| 434 |
+
|
| 435 |
+
blockquote,
|
| 436 |
+
dl,
|
| 437 |
+
dd,
|
| 438 |
+
h1,
|
| 439 |
+
h2,
|
| 440 |
+
h3,
|
| 441 |
+
h4,
|
| 442 |
+
h5,
|
| 443 |
+
h6,
|
| 444 |
+
hr,
|
| 445 |
+
figure,
|
| 446 |
+
p,
|
| 447 |
+
pre {
|
| 448 |
+
margin: 0;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
fieldset {
|
| 452 |
+
margin: 0;
|
| 453 |
+
padding: 0;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
legend {
|
| 457 |
+
padding: 0;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
ol,
|
| 461 |
+
ul,
|
| 462 |
+
menu {
|
| 463 |
+
list-style: none;
|
| 464 |
+
margin: 0;
|
| 465 |
+
padding: 0;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
/*
|
| 469 |
+
Reset default styling for dialogs.
|
| 470 |
+
*/
|
| 471 |
+
|
| 472 |
+
dialog {
|
| 473 |
+
padding: 0;
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/*
|
| 477 |
+
Prevent resizing textareas horizontally by default.
|
| 478 |
+
*/
|
| 479 |
+
|
| 480 |
+
textarea {
|
| 481 |
+
resize: vertical;
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
/*
|
| 485 |
+
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
| 486 |
+
2. Set the default placeholder color to the user's configured gray 400 color.
|
| 487 |
+
*/
|
| 488 |
+
|
| 489 |
+
input::-moz-placeholder, textarea::-moz-placeholder {
|
| 490 |
+
opacity: 1;
|
| 491 |
+
/* 1 */
|
| 492 |
+
color: #9ca3af;
|
| 493 |
+
/* 2 */
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
input::placeholder,
|
| 497 |
+
textarea::placeholder {
|
| 498 |
+
opacity: 1;
|
| 499 |
+
/* 1 */
|
| 500 |
+
color: #9ca3af;
|
| 501 |
+
/* 2 */
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
/*
|
| 505 |
+
Set the default cursor for buttons.
|
| 506 |
+
*/
|
| 507 |
+
|
| 508 |
+
button,
|
| 509 |
+
[role="button"] {
|
| 510 |
+
cursor: pointer;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
/*
|
| 514 |
+
Make sure disabled buttons don't get the pointer cursor.
|
| 515 |
+
*/
|
| 516 |
+
|
| 517 |
+
:disabled {
|
| 518 |
+
cursor: default;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
/*
|
| 522 |
+
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
| 523 |
+
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
| 524 |
+
This can trigger a poorly considered lint error in some tools but is included by design.
|
| 525 |
+
*/
|
| 526 |
+
|
| 527 |
+
img,
|
| 528 |
+
svg,
|
| 529 |
+
video,
|
| 530 |
+
canvas,
|
| 531 |
+
audio,
|
| 532 |
+
iframe,
|
| 533 |
+
embed,
|
| 534 |
+
object {
|
| 535 |
+
display: block;
|
| 536 |
+
/* 1 */
|
| 537 |
+
vertical-align: middle;
|
| 538 |
+
/* 2 */
|
| 539 |
+
}
|
| 540 |
+
|
| 541 |
+
/*
|
| 542 |
+
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
| 543 |
+
*/
|
| 544 |
+
|
| 545 |
+
img,
|
| 546 |
+
video {
|
| 547 |
+
max-width: 100%;
|
| 548 |
+
height: auto;
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
/* Make elements with the HTML hidden attribute stay hidden by default */
|
| 552 |
+
|
| 553 |
+
[hidden] {
|
| 554 |
+
display: none;
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
:root {
|
| 558 |
+
--background: 240 20% 99%;
|
| 559 |
+
/* 1 */
|
| 560 |
+
--foreground: 210 13% 13%;
|
| 561 |
+
/* 12 */
|
| 562 |
+
--card: 240 20% 99%;
|
| 563 |
+
/* 1 */
|
| 564 |
+
--card-foreground: 210 13% 13%;
|
| 565 |
+
/* 12 */
|
| 566 |
+
--popover: 240 20% 99%;
|
| 567 |
+
/* 1 */
|
| 568 |
+
--popover-foreground: 210 13% 13%;
|
| 569 |
+
/* 12 */
|
| 570 |
+
--primary: 210 13% 13%;
|
| 571 |
+
/* 12 */
|
| 572 |
+
--primary-foreground: 240 20% 98%;
|
| 573 |
+
/* 2 */
|
| 574 |
+
--secondary: 240 11% 95%;
|
| 575 |
+
/* 3 */
|
| 576 |
+
--secondary-foreground: 210 13% 13%;
|
| 577 |
+
/* 12 */
|
| 578 |
+
--muted: 240 11% 95%;
|
| 579 |
+
/* 3 */
|
| 580 |
+
--muted-foreground: 220 6% 40%;
|
| 581 |
+
/* 11 */
|
| 582 |
+
--accent: 240 11% 95%;
|
| 583 |
+
/* 3 */
|
| 584 |
+
--accent-foreground: 210 13% 13%;
|
| 585 |
+
/* 12 */
|
| 586 |
+
--destructive: 358 75% 59%;
|
| 587 |
+
/* 9 - red */
|
| 588 |
+
--destructive-foreground: 240 20% 98%;
|
| 589 |
+
/* 2 */
|
| 590 |
+
--border: 240 10% 86%;
|
| 591 |
+
/* 6 */
|
| 592 |
+
--input: 240 10% 86%;
|
| 593 |
+
/* 6 */
|
| 594 |
+
--ring: 210 13% 13%;
|
| 595 |
+
/* 12 */
|
| 596 |
+
--chart-1: 10 78% 54%;
|
| 597 |
+
/* 9 - tomato */
|
| 598 |
+
--chart-2: 173 80% 36%;
|
| 599 |
+
/* 9 - teal */
|
| 600 |
+
--chart-3: 206 100% 50%;
|
| 601 |
+
/* 9 - blue */
|
| 602 |
+
--chart-4: 42 100% 62%;
|
| 603 |
+
/* 9 - amber */
|
| 604 |
+
--chart-5: 23 93% 53%;
|
| 605 |
+
/* 9 - orange */
|
| 606 |
+
}
|
| 607 |
+
|
| 608 |
+
.dark {
|
| 609 |
+
--background: 240 6% 7%;
|
| 610 |
+
/* 1 */
|
| 611 |
+
--foreground: 220 9% 94%;
|
| 612 |
+
/* 12 */
|
| 613 |
+
--card: 240 6% 7%;
|
| 614 |
+
/* 1 */
|
| 615 |
+
--card-foreground: 220 9% 94%;
|
| 616 |
+
/* 12 */
|
| 617 |
+
--popover: 240 6% 7%;
|
| 618 |
+
/* 1 */
|
| 619 |
+
--popover-foreground: 220 9% 94%;
|
| 620 |
+
/* 12 */
|
| 621 |
+
--primary: 220 9% 94%;
|
| 622 |
+
/* 12 */
|
| 623 |
+
--primary-foreground: 220 6% 10%;
|
| 624 |
+
/* 2 */
|
| 625 |
+
--secondary: 225 6% 14%;
|
| 626 |
+
/* 3 */
|
| 627 |
+
--secondary-foreground: 220 9% 94%;
|
| 628 |
+
/* 12 */
|
| 629 |
+
--muted: 225 6% 14%;
|
| 630 |
+
/* 3 */
|
| 631 |
+
--muted-foreground: 216 7% 71%;
|
| 632 |
+
/* 11 */
|
| 633 |
+
--accent: 225 6% 14%;
|
| 634 |
+
/* 3 */
|
| 635 |
+
--accent-foreground: 220 9% 94%;
|
| 636 |
+
/* 12 */
|
| 637 |
+
--destructive: 358 75% 59%;
|
| 638 |
+
/* 9 - red */
|
| 639 |
+
--destructive-foreground: 220 9% 94%;
|
| 640 |
+
/* 12 */
|
| 641 |
+
--border: 213 8% 23%;
|
| 642 |
+
/* 6 */
|
| 643 |
+
--input: 213 8% 23%;
|
| 644 |
+
/* 6 */
|
| 645 |
+
--ring: 220 9% 94%;
|
| 646 |
+
/* 12 */
|
| 647 |
+
--chart-1: 10 78% 54%;
|
| 648 |
+
/* 9 - tomato */
|
| 649 |
+
--chart-2: 173 80% 36%;
|
| 650 |
+
/* 9 - teal */
|
| 651 |
+
--chart-3: 206 100% 50%;
|
| 652 |
+
/* 9 - blue */
|
| 653 |
+
--chart-4: 42 100% 62%;
|
| 654 |
+
/* 9 - amber */
|
| 655 |
+
--chart-5: 23 93% 53%;
|
| 656 |
+
/* 9 - orange */
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
:root:has(.no-bg-scroll) {
|
| 660 |
+
overflow: hidden;
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
* {
|
| 664 |
+
border-color: hsl(var(--border));
|
| 665 |
+
}
|
| 666 |
+
|
| 667 |
+
body {
|
| 668 |
+
min-height: 100vh;
|
| 669 |
+
background-color: hsl(var(--background));
|
| 670 |
+
color: hsl(var(--foreground));
|
| 671 |
+
-webkit-font-smoothing: antialiased;
|
| 672 |
+
-moz-osx-font-smoothing: grayscale;
|
| 673 |
+
font-feature-settings: "rlig" 1, "calt" 1;
|
| 674 |
+
}
|
| 675 |
+
|
| 676 |
+
.container {
|
| 677 |
+
width: 100%;
|
| 678 |
+
margin-right: auto;
|
| 679 |
+
margin-left: auto;
|
| 680 |
+
padding-right: 2rem;
|
| 681 |
+
padding-left: 2rem;
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
@media (min-width: 1400px) {
|
| 685 |
+
.container {
|
| 686 |
+
max-width: 1400px;
|
| 687 |
+
}
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
.sr-only {
|
| 691 |
+
position: absolute;
|
| 692 |
+
width: 1px;
|
| 693 |
+
height: 1px;
|
| 694 |
+
padding: 0;
|
| 695 |
+
margin: -1px;
|
| 696 |
+
overflow: hidden;
|
| 697 |
+
clip: rect(0, 0, 0, 0);
|
| 698 |
+
white-space: nowrap;
|
| 699 |
+
border-width: 0;
|
| 700 |
+
}
|
| 701 |
+
|
| 702 |
+
.pointer-events-none {
|
| 703 |
+
pointer-events: none;
|
| 704 |
+
}
|
| 705 |
+
|
| 706 |
+
.pointer-events-auto {
|
| 707 |
+
pointer-events: auto;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
.invisible {
|
| 711 |
+
visibility: hidden;
|
| 712 |
+
}
|
| 713 |
+
|
| 714 |
+
.static {
|
| 715 |
+
position: static;
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
.fixed {
|
| 719 |
+
position: fixed;
|
| 720 |
+
}
|
| 721 |
+
|
| 722 |
+
.absolute {
|
| 723 |
+
position: absolute;
|
| 724 |
+
}
|
| 725 |
+
|
| 726 |
+
.relative {
|
| 727 |
+
position: relative;
|
| 728 |
+
}
|
| 729 |
+
|
| 730 |
+
.inset-0 {
|
| 731 |
+
inset: 0px;
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
.inset-x-0 {
|
| 735 |
+
left: 0px;
|
| 736 |
+
right: 0px;
|
| 737 |
+
}
|
| 738 |
+
|
| 739 |
+
.inset-y-0 {
|
| 740 |
+
top: 0px;
|
| 741 |
+
bottom: 0px;
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
.-bottom-12 {
|
| 745 |
+
bottom: -3rem;
|
| 746 |
+
}
|
| 747 |
+
|
| 748 |
+
.-left-12 {
|
| 749 |
+
left: -3rem;
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
.-right-12 {
|
| 753 |
+
right: -3rem;
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
.-top-12 {
|
| 757 |
+
top: -3rem;
|
| 758 |
+
}
|
| 759 |
+
|
| 760 |
+
.bottom-0 {
|
| 761 |
+
bottom: 0px;
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
.left-0 {
|
| 765 |
+
left: 0px;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
.left-1\/2 {
|
| 769 |
+
left: 50%;
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
.left-2 {
|
| 773 |
+
left: 0.5rem;
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
.left-\[50\%\] {
|
| 777 |
+
left: 50%;
|
| 778 |
+
}
|
| 779 |
+
|
| 780 |
+
.right-0 {
|
| 781 |
+
right: 0px;
|
| 782 |
+
}
|
| 783 |
+
|
| 784 |
+
.right-2 {
|
| 785 |
+
right: 0.5rem;
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
.right-4 {
|
| 789 |
+
right: 1rem;
|
| 790 |
+
}
|
| 791 |
+
|
| 792 |
+
.top-0 {
|
| 793 |
+
top: 0px;
|
| 794 |
+
}
|
| 795 |
+
|
| 796 |
+
.top-1\/2 {
|
| 797 |
+
top: 50%;
|
| 798 |
+
}
|
| 799 |
+
|
| 800 |
+
.top-2 {
|
| 801 |
+
top: 0.5rem;
|
| 802 |
+
}
|
| 803 |
+
|
| 804 |
+
.top-4 {
|
| 805 |
+
top: 1rem;
|
| 806 |
+
}
|
| 807 |
+
|
| 808 |
+
.top-\[50\%\] {
|
| 809 |
+
top: 50%;
|
| 810 |
+
}
|
| 811 |
+
|
| 812 |
+
.top-full {
|
| 813 |
+
top: 100%;
|
| 814 |
+
}
|
| 815 |
+
|
| 816 |
+
.z-10 {
|
| 817 |
+
z-index: 10;
|
| 818 |
+
}
|
| 819 |
+
|
| 820 |
+
.z-40 {
|
| 821 |
+
z-index: 40;
|
| 822 |
+
}
|
| 823 |
+
|
| 824 |
+
.z-50 {
|
| 825 |
+
z-index: 50;
|
| 826 |
+
}
|
| 827 |
+
|
| 828 |
+
.z-\[100\] {
|
| 829 |
+
z-index: 100;
|
| 830 |
+
}
|
| 831 |
+
|
| 832 |
+
.-mx-1 {
|
| 833 |
+
margin-left: -0.25rem;
|
| 834 |
+
margin-right: -0.25rem;
|
| 835 |
+
}
|
| 836 |
+
|
| 837 |
+
.mx-auto {
|
| 838 |
+
margin-left: auto;
|
| 839 |
+
margin-right: auto;
|
| 840 |
+
}
|
| 841 |
+
|
| 842 |
+
.my-1 {
|
| 843 |
+
margin-top: 0.25rem;
|
| 844 |
+
margin-bottom: 0.25rem;
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
.-ml-4 {
|
| 848 |
+
margin-left: -1rem;
|
| 849 |
+
}
|
| 850 |
+
|
| 851 |
+
.-mt-4 {
|
| 852 |
+
margin-top: -1rem;
|
| 853 |
+
}
|
| 854 |
+
|
| 855 |
+
.mb-1 {
|
| 856 |
+
margin-bottom: 0.25rem;
|
| 857 |
+
}
|
| 858 |
+
|
| 859 |
+
.mr-1\.5 {
|
| 860 |
+
margin-right: 0.375rem;
|
| 861 |
+
}
|
| 862 |
+
|
| 863 |
+
.mt-2 {
|
| 864 |
+
margin-top: 0.5rem;
|
| 865 |
+
}
|
| 866 |
+
|
| 867 |
+
.mt-\[13vh\] {
|
| 868 |
+
margin-top: 13vh;
|
| 869 |
+
}
|
| 870 |
+
|
| 871 |
+
.mt-\[8vh\] {
|
| 872 |
+
margin-top: 8vh;
|
| 873 |
+
}
|
| 874 |
+
|
| 875 |
+
.mt-8 {
|
| 876 |
+
margin-top: 2rem;
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
.mt-5 {
|
| 880 |
+
margin-top: 1.25rem;
|
| 881 |
+
}
|
| 882 |
+
|
| 883 |
+
.block {
|
| 884 |
+
display: block;
|
| 885 |
+
}
|
| 886 |
+
|
| 887 |
+
.flex {
|
| 888 |
+
display: flex;
|
| 889 |
+
}
|
| 890 |
+
|
| 891 |
+
.inline-flex {
|
| 892 |
+
display: inline-flex;
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
.table {
|
| 896 |
+
display: table;
|
| 897 |
+
}
|
| 898 |
+
|
| 899 |
+
.grid {
|
| 900 |
+
display: grid;
|
| 901 |
+
}
|
| 902 |
+
|
| 903 |
+
.contents {
|
| 904 |
+
display: contents;
|
| 905 |
+
}
|
| 906 |
+
|
| 907 |
+
.hidden {
|
| 908 |
+
display: none;
|
| 909 |
+
}
|
| 910 |
+
|
| 911 |
+
.aspect-square {
|
| 912 |
+
aspect-ratio: 1 / 1;
|
| 913 |
+
}
|
| 914 |
+
|
| 915 |
+
.size-4 {
|
| 916 |
+
width: 1rem;
|
| 917 |
+
height: 1rem;
|
| 918 |
+
}
|
| 919 |
+
|
| 920 |
+
.size-5 {
|
| 921 |
+
width: 1.25rem;
|
| 922 |
+
height: 1.25rem;
|
| 923 |
+
}
|
| 924 |
+
|
| 925 |
+
.h-10 {
|
| 926 |
+
height: 2.5rem;
|
| 927 |
+
}
|
| 928 |
+
|
| 929 |
+
.h-11 {
|
| 930 |
+
height: 2.75rem;
|
| 931 |
+
}
|
| 932 |
+
|
| 933 |
+
.h-12 {
|
| 934 |
+
height: 3rem;
|
| 935 |
+
}
|
| 936 |
+
|
| 937 |
+
.h-2 {
|
| 938 |
+
height: 0.5rem;
|
| 939 |
+
}
|
| 940 |
+
|
| 941 |
+
.h-2\.5 {
|
| 942 |
+
height: 0.625rem;
|
| 943 |
+
}
|
| 944 |
+
|
| 945 |
+
.h-3\.5 {
|
| 946 |
+
height: 0.875rem;
|
| 947 |
+
}
|
| 948 |
+
|
| 949 |
+
.h-4 {
|
| 950 |
+
height: 1rem;
|
| 951 |
+
}
|
| 952 |
+
|
| 953 |
+
.h-5 {
|
| 954 |
+
height: 1.25rem;
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
.h-6 {
|
| 958 |
+
height: 1.5rem;
|
| 959 |
+
}
|
| 960 |
+
|
| 961 |
+
.h-8 {
|
| 962 |
+
height: 2rem;
|
| 963 |
+
}
|
| 964 |
+
|
| 965 |
+
.h-9 {
|
| 966 |
+
height: 2.25rem;
|
| 967 |
+
}
|
| 968 |
+
|
| 969 |
+
.h-\[1\.5px\] {
|
| 970 |
+
height: 1.5px;
|
| 971 |
+
}
|
| 972 |
+
|
| 973 |
+
.h-\[27px\] {
|
| 974 |
+
height: 27px;
|
| 975 |
+
}
|
| 976 |
+
|
| 977 |
+
.h-\[377px\] {
|
| 978 |
+
height: 377px;
|
| 979 |
+
}
|
| 980 |
+
|
| 981 |
+
.h-\[55px\] {
|
| 982 |
+
height: 55px;
|
| 983 |
+
}
|
| 984 |
+
|
| 985 |
+
.h-full {
|
| 986 |
+
height: 100%;
|
| 987 |
+
}
|
| 988 |
+
|
| 989 |
+
.h-px {
|
| 990 |
+
height: 1px;
|
| 991 |
+
}
|
| 992 |
+
|
| 993 |
+
.h-\[21px\] {
|
| 994 |
+
height: 21px;
|
| 995 |
+
}
|
| 996 |
+
|
| 997 |
+
.max-h-96 {
|
| 998 |
+
max-height: 24rem;
|
| 999 |
+
}
|
| 1000 |
+
|
| 1001 |
+
.max-h-screen {
|
| 1002 |
+
max-height: 100vh;
|
| 1003 |
+
}
|
| 1004 |
+
|
| 1005 |
+
.min-h-0 {
|
| 1006 |
+
min-height: 0px;
|
| 1007 |
+
}
|
| 1008 |
+
|
| 1009 |
+
.min-h-\[55px\] {
|
| 1010 |
+
min-height: 55px;
|
| 1011 |
+
}
|
| 1012 |
+
|
| 1013 |
+
.min-h-\[80px\] {
|
| 1014 |
+
min-height: 80px;
|
| 1015 |
+
}
|
| 1016 |
+
|
| 1017 |
+
.min-h-screen {
|
| 1018 |
+
min-height: 100vh;
|
| 1019 |
+
}
|
| 1020 |
+
|
| 1021 |
+
.w-10 {
|
| 1022 |
+
width: 2.5rem;
|
| 1023 |
+
}
|
| 1024 |
+
|
| 1025 |
+
.w-11 {
|
| 1026 |
+
width: 2.75rem;
|
| 1027 |
+
}
|
| 1028 |
+
|
| 1029 |
+
.w-2\.5 {
|
| 1030 |
+
width: 0.625rem;
|
| 1031 |
+
}
|
| 1032 |
+
|
| 1033 |
+
.w-3\.5 {
|
| 1034 |
+
width: 0.875rem;
|
| 1035 |
+
}
|
| 1036 |
+
|
| 1037 |
+
.w-3\/4 {
|
| 1038 |
+
width: 75%;
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
.w-4 {
|
| 1042 |
+
width: 1rem;
|
| 1043 |
+
}
|
| 1044 |
+
|
| 1045 |
+
.w-48 {
|
| 1046 |
+
width: 12rem;
|
| 1047 |
+
}
|
| 1048 |
+
|
| 1049 |
+
.w-5 {
|
| 1050 |
+
width: 1.25rem;
|
| 1051 |
+
}
|
| 1052 |
+
|
| 1053 |
+
.w-8 {
|
| 1054 |
+
width: 2rem;
|
| 1055 |
+
}
|
| 1056 |
+
|
| 1057 |
+
.w-9 {
|
| 1058 |
+
width: 2.25rem;
|
| 1059 |
+
}
|
| 1060 |
+
|
| 1061 |
+
.w-\[1\.5px\] {
|
| 1062 |
+
width: 1.5px;
|
| 1063 |
+
}
|
| 1064 |
+
|
| 1065 |
+
.w-full {
|
| 1066 |
+
width: 100%;
|
| 1067 |
+
}
|
| 1068 |
+
|
| 1069 |
+
.min-w-0 {
|
| 1070 |
+
min-width: 0px;
|
| 1071 |
+
}
|
| 1072 |
+
|
| 1073 |
+
.min-w-\[8rem\] {
|
| 1074 |
+
min-width: 8rem;
|
| 1075 |
+
}
|
| 1076 |
+
|
| 1077 |
+
.max-w-lg {
|
| 1078 |
+
max-width: 32rem;
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
.max-w-screen-md {
|
| 1082 |
+
max-width: 768px;
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
+
.flex-1 {
|
| 1086 |
+
flex: 1 1 0%;
|
| 1087 |
+
}
|
| 1088 |
+
|
| 1089 |
+
.shrink-0 {
|
| 1090 |
+
flex-shrink: 0;
|
| 1091 |
+
}
|
| 1092 |
+
|
| 1093 |
+
.grow {
|
| 1094 |
+
flex-grow: 1;
|
| 1095 |
+
}
|
| 1096 |
+
|
| 1097 |
+
.grow-0 {
|
| 1098 |
+
flex-grow: 0;
|
| 1099 |
+
}
|
| 1100 |
+
|
| 1101 |
+
.basis-full {
|
| 1102 |
+
flex-basis: 100%;
|
| 1103 |
+
}
|
| 1104 |
+
|
| 1105 |
+
.caption-bottom {
|
| 1106 |
+
caption-side: bottom;
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
.-translate-x-1\/2 {
|
| 1110 |
+
--tw-translate-x: -50%;
|
| 1111 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1112 |
+
}
|
| 1113 |
+
|
| 1114 |
+
.-translate-y-1\/2 {
|
| 1115 |
+
--tw-translate-y: -50%;
|
| 1116 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1117 |
+
}
|
| 1118 |
+
|
| 1119 |
+
.translate-x-\[-50\%\] {
|
| 1120 |
+
--tw-translate-x: -50%;
|
| 1121 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1122 |
+
}
|
| 1123 |
+
|
| 1124 |
+
.translate-y-\[-50\%\] {
|
| 1125 |
+
--tw-translate-y: -50%;
|
| 1126 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1127 |
+
}
|
| 1128 |
+
|
| 1129 |
+
.rotate-90 {
|
| 1130 |
+
--tw-rotate: 90deg;
|
| 1131 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1132 |
+
}
|
| 1133 |
+
|
| 1134 |
+
.transform {
|
| 1135 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 1136 |
+
}
|
| 1137 |
+
|
| 1138 |
+
@keyframes pulse {
|
| 1139 |
+
50% {
|
| 1140 |
+
opacity: .5;
|
| 1141 |
+
}
|
| 1142 |
+
}
|
| 1143 |
+
|
| 1144 |
+
.animate-pulse {
|
| 1145 |
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
| 1146 |
+
}
|
| 1147 |
+
|
| 1148 |
+
@keyframes spin {
|
| 1149 |
+
to {
|
| 1150 |
+
transform: rotate(360deg);
|
| 1151 |
+
}
|
| 1152 |
+
}
|
| 1153 |
+
|
| 1154 |
+
.animate-spin {
|
| 1155 |
+
animation: spin 1s linear infinite;
|
| 1156 |
+
}
|
| 1157 |
+
|
| 1158 |
+
.cursor-default {
|
| 1159 |
+
cursor: default;
|
| 1160 |
+
}
|
| 1161 |
+
|
| 1162 |
+
.cursor-pointer {
|
| 1163 |
+
cursor: pointer;
|
| 1164 |
+
}
|
| 1165 |
+
|
| 1166 |
+
.touch-none {
|
| 1167 |
+
touch-action: none;
|
| 1168 |
+
}
|
| 1169 |
+
|
| 1170 |
+
.select-none {
|
| 1171 |
+
-webkit-user-select: none;
|
| 1172 |
+
-moz-user-select: none;
|
| 1173 |
+
user-select: none;
|
| 1174 |
+
}
|
| 1175 |
+
|
| 1176 |
+
.resize {
|
| 1177 |
+
resize: both;
|
| 1178 |
+
}
|
| 1179 |
+
|
| 1180 |
+
.grid-flow-col {
|
| 1181 |
+
grid-auto-flow: column;
|
| 1182 |
+
}
|
| 1183 |
+
|
| 1184 |
+
.grid-cols-1 {
|
| 1185 |
+
grid-template-columns: repeat(1, minmax(0, 1fr));
|
| 1186 |
+
}
|
| 1187 |
+
|
| 1188 |
+
.grid-rows-\[1fr_1fr\] {
|
| 1189 |
+
grid-template-rows: 1fr 1fr;
|
| 1190 |
+
}
|
| 1191 |
+
|
| 1192 |
+
.grid-rows-\[auto_0px\] {
|
| 1193 |
+
grid-template-rows: auto 0px;
|
| 1194 |
+
}
|
| 1195 |
+
|
| 1196 |
+
.grid-rows-\[auto_1fr_auto\] {
|
| 1197 |
+
grid-template-rows: auto 1fr auto;
|
| 1198 |
+
}
|
| 1199 |
+
|
| 1200 |
+
.grid-rows-\[auto_auto_1fr\] {
|
| 1201 |
+
grid-template-rows: auto auto 1fr;
|
| 1202 |
+
}
|
| 1203 |
+
|
| 1204 |
+
.grid-rows-\[minmax\(0\2c 55px\)_minmax\(0\2c 1fr\)\] {
|
| 1205 |
+
grid-template-rows: minmax(0,55px) minmax(0,1fr);
|
| 1206 |
+
}
|
| 1207 |
+
|
| 1208 |
+
.flex-col {
|
| 1209 |
+
flex-direction: column;
|
| 1210 |
+
}
|
| 1211 |
+
|
| 1212 |
+
.flex-col-reverse {
|
| 1213 |
+
flex-direction: column-reverse;
|
| 1214 |
+
}
|
| 1215 |
+
|
| 1216 |
+
.flex-wrap {
|
| 1217 |
+
flex-wrap: wrap;
|
| 1218 |
+
}
|
| 1219 |
+
|
| 1220 |
+
.content-center {
|
| 1221 |
+
align-content: center;
|
| 1222 |
+
}
|
| 1223 |
+
|
| 1224 |
+
.content-start {
|
| 1225 |
+
align-content: flex-start;
|
| 1226 |
+
}
|
| 1227 |
+
|
| 1228 |
+
.items-end {
|
| 1229 |
+
align-items: flex-end;
|
| 1230 |
+
}
|
| 1231 |
+
|
| 1232 |
+
.items-center {
|
| 1233 |
+
align-items: center;
|
| 1234 |
+
}
|
| 1235 |
+
|
| 1236 |
+
.justify-end {
|
| 1237 |
+
justify-content: flex-end;
|
| 1238 |
+
}
|
| 1239 |
+
|
| 1240 |
+
.justify-center {
|
| 1241 |
+
justify-content: center;
|
| 1242 |
+
}
|
| 1243 |
+
|
| 1244 |
+
.justify-between {
|
| 1245 |
+
justify-content: space-between;
|
| 1246 |
+
}
|
| 1247 |
+
|
| 1248 |
+
.justify-items-center {
|
| 1249 |
+
justify-items: center;
|
| 1250 |
+
}
|
| 1251 |
+
|
| 1252 |
+
.gap-1\.5 {
|
| 1253 |
+
gap: 0.375rem;
|
| 1254 |
+
}
|
| 1255 |
+
|
| 1256 |
+
.gap-2 {
|
| 1257 |
+
gap: 0.5rem;
|
| 1258 |
+
}
|
| 1259 |
+
|
| 1260 |
+
.gap-3 {
|
| 1261 |
+
gap: 0.75rem;
|
| 1262 |
+
}
|
| 1263 |
+
|
| 1264 |
+
.gap-4 {
|
| 1265 |
+
gap: 1rem;
|
| 1266 |
+
}
|
| 1267 |
+
|
| 1268 |
+
.gap-5 {
|
| 1269 |
+
gap: 1.25rem;
|
| 1270 |
+
}
|
| 1271 |
+
|
| 1272 |
+
.gap-8 {
|
| 1273 |
+
gap: 2rem;
|
| 1274 |
+
}
|
| 1275 |
+
|
| 1276 |
+
.gap-\[3px\] {
|
| 1277 |
+
gap: 3px;
|
| 1278 |
+
}
|
| 1279 |
+
|
| 1280 |
+
.gap-px {
|
| 1281 |
+
gap: 1px;
|
| 1282 |
+
}
|
| 1283 |
+
|
| 1284 |
+
.gap-x-1\.5 {
|
| 1285 |
+
-moz-column-gap: 0.375rem;
|
| 1286 |
+
column-gap: 0.375rem;
|
| 1287 |
+
}
|
| 1288 |
+
|
| 1289 |
+
.gap-x-3 {
|
| 1290 |
+
-moz-column-gap: 0.75rem;
|
| 1291 |
+
column-gap: 0.75rem;
|
| 1292 |
+
}
|
| 1293 |
+
|
| 1294 |
+
.gap-x-5 {
|
| 1295 |
+
-moz-column-gap: 1.25rem;
|
| 1296 |
+
column-gap: 1.25rem;
|
| 1297 |
+
}
|
| 1298 |
+
|
| 1299 |
+
.gap-y-3 {
|
| 1300 |
+
row-gap: 0.75rem;
|
| 1301 |
+
}
|
| 1302 |
+
|
| 1303 |
+
.gap-y-8 {
|
| 1304 |
+
row-gap: 2rem;
|
| 1305 |
+
}
|
| 1306 |
+
|
| 1307 |
+
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
|
| 1308 |
+
--tw-space-x-reverse: 0;
|
| 1309 |
+
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
|
| 1310 |
+
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
|
| 1311 |
+
}
|
| 1312 |
+
|
| 1313 |
+
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
|
| 1314 |
+
--tw-space-x-reverse: 0;
|
| 1315 |
+
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
| 1316 |
+
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
| 1317 |
+
}
|
| 1318 |
+
|
| 1319 |
+
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
| 1320 |
+
--tw-space-x-reverse: 0;
|
| 1321 |
+
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
| 1322 |
+
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
| 1323 |
+
}
|
| 1324 |
+
|
| 1325 |
+
.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
|
| 1326 |
+
--tw-space-y-reverse: 0;
|
| 1327 |
+
margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
|
| 1328 |
+
margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
|
| 1329 |
+
}
|
| 1330 |
+
|
| 1331 |
+
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
| 1332 |
+
--tw-space-y-reverse: 0;
|
| 1333 |
+
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
| 1334 |
+
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
| 1335 |
+
}
|
| 1336 |
+
|
| 1337 |
+
.space-x-8 > :not([hidden]) ~ :not([hidden]) {
|
| 1338 |
+
--tw-space-x-reverse: 0;
|
| 1339 |
+
margin-right: calc(2rem * var(--tw-space-x-reverse));
|
| 1340 |
+
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
|
| 1341 |
+
}
|
| 1342 |
+
|
| 1343 |
+
.self-stretch {
|
| 1344 |
+
align-self: stretch;
|
| 1345 |
+
}
|
| 1346 |
+
|
| 1347 |
+
.overflow-auto {
|
| 1348 |
+
overflow: auto;
|
| 1349 |
+
}
|
| 1350 |
+
|
| 1351 |
+
.overflow-hidden {
|
| 1352 |
+
overflow: hidden;
|
| 1353 |
+
}
|
| 1354 |
+
|
| 1355 |
+
.whitespace-nowrap {
|
| 1356 |
+
white-space: nowrap;
|
| 1357 |
+
}
|
| 1358 |
+
|
| 1359 |
+
.break-words {
|
| 1360 |
+
overflow-wrap: break-word;
|
| 1361 |
+
}
|
| 1362 |
+
|
| 1363 |
+
.\!rounded-full {
|
| 1364 |
+
border-radius: 9999px !important;
|
| 1365 |
+
}
|
| 1366 |
+
|
| 1367 |
+
.rounded-\[inherit\] {
|
| 1368 |
+
border-radius: inherit;
|
| 1369 |
+
}
|
| 1370 |
+
|
| 1371 |
+
.rounded-full {
|
| 1372 |
+
border-radius: 9999px;
|
| 1373 |
+
}
|
| 1374 |
+
|
| 1375 |
+
.rounded-lg {
|
| 1376 |
+
border-radius: var(--radius);
|
| 1377 |
+
}
|
| 1378 |
+
|
| 1379 |
+
.rounded-md {
|
| 1380 |
+
border-radius: calc(var(--radius) - 2px);
|
| 1381 |
+
}
|
| 1382 |
+
|
| 1383 |
+
.rounded-none {
|
| 1384 |
+
border-radius: 0px;
|
| 1385 |
+
}
|
| 1386 |
+
|
| 1387 |
+
.rounded-sm {
|
| 1388 |
+
border-radius: calc(var(--radius) - 4px);
|
| 1389 |
+
}
|
| 1390 |
+
|
| 1391 |
+
.border {
|
| 1392 |
+
border-width: 1px;
|
| 1393 |
+
}
|
| 1394 |
+
|
| 1395 |
+
.border-2 {
|
| 1396 |
+
border-width: 2px;
|
| 1397 |
+
}
|
| 1398 |
+
|
| 1399 |
+
.border-b {
|
| 1400 |
+
border-bottom-width: 1px;
|
| 1401 |
+
}
|
| 1402 |
+
|
| 1403 |
+
.border-l {
|
| 1404 |
+
border-left-width: 1px;
|
| 1405 |
+
}
|
| 1406 |
+
|
| 1407 |
+
.border-r {
|
| 1408 |
+
border-right-width: 1px;
|
| 1409 |
+
}
|
| 1410 |
+
|
| 1411 |
+
.border-t {
|
| 1412 |
+
border-top-width: 1px;
|
| 1413 |
+
}
|
| 1414 |
+
|
| 1415 |
+
.border-dashed {
|
| 1416 |
+
border-style: dashed;
|
| 1417 |
+
}
|
| 1418 |
+
|
| 1419 |
+
.border-destructive {
|
| 1420 |
+
border-color: hsl(var(--destructive));
|
| 1421 |
+
}
|
| 1422 |
+
|
| 1423 |
+
.border-destructive\/50 {
|
| 1424 |
+
border-color: hsl(var(--destructive) / 0.5);
|
| 1425 |
+
}
|
| 1426 |
+
|
| 1427 |
+
.border-input {
|
| 1428 |
+
border-color: hsl(var(--input));
|
| 1429 |
+
}
|
| 1430 |
+
|
| 1431 |
+
.border-primary {
|
| 1432 |
+
border-color: hsl(var(--primary));
|
| 1433 |
+
}
|
| 1434 |
+
|
| 1435 |
+
.border-transparent {
|
| 1436 |
+
border-color: transparent;
|
| 1437 |
+
}
|
| 1438 |
+
|
| 1439 |
+
.border-l-transparent {
|
| 1440 |
+
border-left-color: transparent;
|
| 1441 |
+
}
|
| 1442 |
+
|
| 1443 |
+
.border-t-transparent {
|
| 1444 |
+
border-top-color: transparent;
|
| 1445 |
+
}
|
| 1446 |
+
|
| 1447 |
+
.bg-background {
|
| 1448 |
+
background-color: hsl(var(--background));
|
| 1449 |
+
}
|
| 1450 |
+
|
| 1451 |
+
.bg-black {
|
| 1452 |
+
--tw-bg-opacity: 1;
|
| 1453 |
+
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
| 1454 |
+
}
|
| 1455 |
+
|
| 1456 |
+
.bg-black\/80 {
|
| 1457 |
+
background-color: rgb(0 0 0 / 0.8);
|
| 1458 |
+
}
|
| 1459 |
+
|
| 1460 |
+
.bg-blue-500 {
|
| 1461 |
+
--tw-bg-opacity: 1;
|
| 1462 |
+
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
| 1463 |
+
}
|
| 1464 |
+
|
| 1465 |
+
.bg-border {
|
| 1466 |
+
background-color: hsl(var(--border));
|
| 1467 |
+
}
|
| 1468 |
+
|
| 1469 |
+
.bg-card {
|
| 1470 |
+
background-color: hsl(var(--card));
|
| 1471 |
+
}
|
| 1472 |
+
|
| 1473 |
+
.bg-destructive {
|
| 1474 |
+
background-color: hsl(var(--destructive));
|
| 1475 |
+
}
|
| 1476 |
+
|
| 1477 |
+
.bg-input {
|
| 1478 |
+
background-color: hsl(var(--input));
|
| 1479 |
+
}
|
| 1480 |
+
|
| 1481 |
+
.bg-muted {
|
| 1482 |
+
background-color: hsl(var(--muted));
|
| 1483 |
+
}
|
| 1484 |
+
|
| 1485 |
+
.bg-muted\/50 {
|
| 1486 |
+
background-color: hsl(var(--muted) / 0.5);
|
| 1487 |
+
}
|
| 1488 |
+
|
| 1489 |
+
.bg-popover {
|
| 1490 |
+
background-color: hsl(var(--popover));
|
| 1491 |
+
}
|
| 1492 |
+
|
| 1493 |
+
.bg-primary {
|
| 1494 |
+
background-color: hsl(var(--primary));
|
| 1495 |
+
}
|
| 1496 |
+
|
| 1497 |
+
.bg-red-300 {
|
| 1498 |
+
--tw-bg-opacity: 1;
|
| 1499 |
+
background-color: rgb(252 165 165 / var(--tw-bg-opacity));
|
| 1500 |
+
}
|
| 1501 |
+
|
| 1502 |
+
.bg-red-500 {
|
| 1503 |
+
--tw-bg-opacity: 1;
|
| 1504 |
+
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
| 1505 |
+
}
|
| 1506 |
+
|
| 1507 |
+
.bg-secondary {
|
| 1508 |
+
background-color: hsl(var(--secondary));
|
| 1509 |
+
}
|
| 1510 |
+
|
| 1511 |
+
.bg-white {
|
| 1512 |
+
--tw-bg-opacity: 1;
|
| 1513 |
+
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
| 1514 |
+
}
|
| 1515 |
+
|
| 1516 |
+
.bg-\[\#0A66C2\] {
|
| 1517 |
+
--tw-bg-opacity: 1;
|
| 1518 |
+
background-color: rgb(10 102 194 / var(--tw-bg-opacity));
|
| 1519 |
+
}
|
| 1520 |
+
|
| 1521 |
+
.bg-gradient-to-r {
|
| 1522 |
+
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
| 1523 |
+
}
|
| 1524 |
+
|
| 1525 |
+
.bg-gradient-to-t {
|
| 1526 |
+
background-image: linear-gradient(to top, var(--tw-gradient-stops));
|
| 1527 |
+
}
|
| 1528 |
+
|
| 1529 |
+
.from-\[\#fcfcfd\] {
|
| 1530 |
+
--tw-gradient-from: #fcfcfd var(--tw-gradient-from-position);
|
| 1531 |
+
--tw-gradient-to: rgb(252 252 253 / 0) var(--tw-gradient-to-position);
|
| 1532 |
+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
| 1533 |
+
}
|
| 1534 |
+
|
| 1535 |
+
.from-black {
|
| 1536 |
+
--tw-gradient-from: #000 var(--tw-gradient-from-position);
|
| 1537 |
+
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
|
| 1538 |
+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
| 1539 |
+
}
|
| 1540 |
+
|
| 1541 |
+
.to-slate-700 {
|
| 1542 |
+
--tw-gradient-to: #334155 var(--tw-gradient-to-position);
|
| 1543 |
+
}
|
| 1544 |
+
|
| 1545 |
+
.bg-clip-text {
|
| 1546 |
+
-webkit-background-clip: text;
|
| 1547 |
+
background-clip: text;
|
| 1548 |
+
}
|
| 1549 |
+
|
| 1550 |
+
.fill-current {
|
| 1551 |
+
fill: currentColor;
|
| 1552 |
+
}
|
| 1553 |
+
|
| 1554 |
+
.object-contain {
|
| 1555 |
+
-o-object-fit: contain;
|
| 1556 |
+
object-fit: contain;
|
| 1557 |
+
}
|
| 1558 |
+
|
| 1559 |
+
.p-1 {
|
| 1560 |
+
padding: 0.25rem;
|
| 1561 |
+
}
|
| 1562 |
+
|
| 1563 |
+
.p-10 {
|
| 1564 |
+
padding: 2.5rem;
|
| 1565 |
+
}
|
| 1566 |
+
|
| 1567 |
+
.p-2 {
|
| 1568 |
+
padding: 0.5rem;
|
| 1569 |
+
}
|
| 1570 |
+
|
| 1571 |
+
.p-3 {
|
| 1572 |
+
padding: 0.75rem;
|
| 1573 |
+
}
|
| 1574 |
+
|
| 1575 |
+
.p-4 {
|
| 1576 |
+
padding: 1rem;
|
| 1577 |
+
}
|
| 1578 |
+
|
| 1579 |
+
.p-5 {
|
| 1580 |
+
padding: 1.25rem;
|
| 1581 |
+
}
|
| 1582 |
+
|
| 1583 |
+
.p-6 {
|
| 1584 |
+
padding: 1.5rem;
|
| 1585 |
+
}
|
| 1586 |
+
|
| 1587 |
+
.p-8 {
|
| 1588 |
+
padding: 2rem;
|
| 1589 |
+
}
|
| 1590 |
+
|
| 1591 |
+
.p-\[1px\] {
|
| 1592 |
+
padding: 1px;
|
| 1593 |
+
}
|
| 1594 |
+
|
| 1595 |
+
.px-2 {
|
| 1596 |
+
padding-left: 0.5rem;
|
| 1597 |
+
padding-right: 0.5rem;
|
| 1598 |
+
}
|
| 1599 |
+
|
| 1600 |
+
.px-2\.5 {
|
| 1601 |
+
padding-left: 0.625rem;
|
| 1602 |
+
padding-right: 0.625rem;
|
| 1603 |
+
}
|
| 1604 |
+
|
| 1605 |
+
.px-3 {
|
| 1606 |
+
padding-left: 0.75rem;
|
| 1607 |
+
padding-right: 0.75rem;
|
| 1608 |
+
}
|
| 1609 |
+
|
| 1610 |
+
.px-4 {
|
| 1611 |
+
padding-left: 1rem;
|
| 1612 |
+
padding-right: 1rem;
|
| 1613 |
+
}
|
| 1614 |
+
|
| 1615 |
+
.px-5 {
|
| 1616 |
+
padding-left: 1.25rem;
|
| 1617 |
+
padding-right: 1.25rem;
|
| 1618 |
+
}
|
| 1619 |
+
|
| 1620 |
+
.px-8 {
|
| 1621 |
+
padding-left: 2rem;
|
| 1622 |
+
padding-right: 2rem;
|
| 1623 |
+
}
|
| 1624 |
+
|
| 1625 |
+
.py-0\.5 {
|
| 1626 |
+
padding-top: 0.125rem;
|
| 1627 |
+
padding-bottom: 0.125rem;
|
| 1628 |
+
}
|
| 1629 |
+
|
| 1630 |
+
.py-1 {
|
| 1631 |
+
padding-top: 0.25rem;
|
| 1632 |
+
padding-bottom: 0.25rem;
|
| 1633 |
+
}
|
| 1634 |
+
|
| 1635 |
+
.py-1\.5 {
|
| 1636 |
+
padding-top: 0.375rem;
|
| 1637 |
+
padding-bottom: 0.375rem;
|
| 1638 |
+
}
|
| 1639 |
+
|
| 1640 |
+
.py-2 {
|
| 1641 |
+
padding-top: 0.5rem;
|
| 1642 |
+
padding-bottom: 0.5rem;
|
| 1643 |
+
}
|
| 1644 |
+
|
| 1645 |
+
.py-4 {
|
| 1646 |
+
padding-top: 1rem;
|
| 1647 |
+
padding-bottom: 1rem;
|
| 1648 |
+
}
|
| 1649 |
+
|
| 1650 |
+
.py-5 {
|
| 1651 |
+
padding-top: 1.25rem;
|
| 1652 |
+
padding-bottom: 1.25rem;
|
| 1653 |
+
}
|
| 1654 |
+
|
| 1655 |
+
.pb-4 {
|
| 1656 |
+
padding-bottom: 1rem;
|
| 1657 |
+
}
|
| 1658 |
+
|
| 1659 |
+
.pl-10 {
|
| 1660 |
+
padding-left: 2.5rem;
|
| 1661 |
+
}
|
| 1662 |
+
|
| 1663 |
+
.pl-4 {
|
| 1664 |
+
padding-left: 1rem;
|
| 1665 |
+
}
|
| 1666 |
+
|
| 1667 |
+
.pl-8 {
|
| 1668 |
+
padding-left: 2rem;
|
| 1669 |
+
}
|
| 1670 |
+
|
| 1671 |
+
.pr-2 {
|
| 1672 |
+
padding-right: 0.5rem;
|
| 1673 |
+
}
|
| 1674 |
+
|
| 1675 |
+
.pr-8 {
|
| 1676 |
+
padding-right: 2rem;
|
| 1677 |
+
}
|
| 1678 |
+
|
| 1679 |
+
.pt-0 {
|
| 1680 |
+
padding-top: 0px;
|
| 1681 |
+
}
|
| 1682 |
+
|
| 1683 |
+
.pt-4 {
|
| 1684 |
+
padding-top: 1rem;
|
| 1685 |
+
}
|
| 1686 |
+
|
| 1687 |
+
.pt-\[7\%\] {
|
| 1688 |
+
padding-top: 7%;
|
| 1689 |
+
}
|
| 1690 |
+
|
| 1691 |
+
.text-left {
|
| 1692 |
+
text-align: left;
|
| 1693 |
+
}
|
| 1694 |
+
|
| 1695 |
+
.text-center {
|
| 1696 |
+
text-align: center;
|
| 1697 |
+
}
|
| 1698 |
+
|
| 1699 |
+
.align-middle {
|
| 1700 |
+
vertical-align: middle;
|
| 1701 |
+
}
|
| 1702 |
+
|
| 1703 |
+
.font-mono {
|
| 1704 |
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
| 1705 |
+
}
|
| 1706 |
+
|
| 1707 |
+
.text-2xl {
|
| 1708 |
+
font-size: 1.5rem;
|
| 1709 |
+
line-height: 2rem;
|
| 1710 |
+
}
|
| 1711 |
+
|
| 1712 |
+
.text-3xl {
|
| 1713 |
+
font-size: 1.875rem;
|
| 1714 |
+
line-height: 2.25rem;
|
| 1715 |
+
}
|
| 1716 |
+
|
| 1717 |
+
.text-5xl {
|
| 1718 |
+
font-size: 3rem;
|
| 1719 |
+
line-height: 1;
|
| 1720 |
+
}
|
| 1721 |
+
|
| 1722 |
+
.text-base {
|
| 1723 |
+
font-size: 1rem;
|
| 1724 |
+
line-height: 1.5rem;
|
| 1725 |
+
}
|
| 1726 |
+
|
| 1727 |
+
.text-lg {
|
| 1728 |
+
font-size: 1.125rem;
|
| 1729 |
+
line-height: 1.75rem;
|
| 1730 |
+
}
|
| 1731 |
+
|
| 1732 |
+
.text-sm {
|
| 1733 |
+
font-size: 0.875rem;
|
| 1734 |
+
line-height: 1.25rem;
|
| 1735 |
+
}
|
| 1736 |
+
|
| 1737 |
+
.text-xl {
|
| 1738 |
+
font-size: 1.25rem;
|
| 1739 |
+
line-height: 1.75rem;
|
| 1740 |
+
}
|
| 1741 |
+
|
| 1742 |
+
.text-xs {
|
| 1743 |
+
font-size: 0.75rem;
|
| 1744 |
+
line-height: 1rem;
|
| 1745 |
+
}
|
| 1746 |
+
|
| 1747 |
+
.font-bold {
|
| 1748 |
+
font-weight: 700;
|
| 1749 |
+
}
|
| 1750 |
+
|
| 1751 |
+
.font-medium {
|
| 1752 |
+
font-weight: 500;
|
| 1753 |
+
}
|
| 1754 |
+
|
| 1755 |
+
.font-normal {
|
| 1756 |
+
font-weight: 400;
|
| 1757 |
+
}
|
| 1758 |
+
|
| 1759 |
+
.font-semibold {
|
| 1760 |
+
font-weight: 600;
|
| 1761 |
+
}
|
| 1762 |
+
|
| 1763 |
+
.capitalize {
|
| 1764 |
+
text-transform: capitalize;
|
| 1765 |
+
}
|
| 1766 |
+
|
| 1767 |
+
.leading-none {
|
| 1768 |
+
line-height: 1;
|
| 1769 |
+
}
|
| 1770 |
+
|
| 1771 |
+
.tracking-tight {
|
| 1772 |
+
letter-spacing: -0.025em;
|
| 1773 |
+
}
|
| 1774 |
+
|
| 1775 |
+
.tracking-wide {
|
| 1776 |
+
letter-spacing: 0.025em;
|
| 1777 |
+
}
|
| 1778 |
+
|
| 1779 |
+
.text-card-foreground {
|
| 1780 |
+
color: hsl(var(--card-foreground));
|
| 1781 |
+
}
|
| 1782 |
+
|
| 1783 |
+
.text-current {
|
| 1784 |
+
color: currentColor;
|
| 1785 |
+
}
|
| 1786 |
+
|
| 1787 |
+
.text-destructive {
|
| 1788 |
+
color: hsl(var(--destructive));
|
| 1789 |
+
}
|
| 1790 |
+
|
| 1791 |
+
.text-destructive-foreground {
|
| 1792 |
+
color: hsl(var(--destructive-foreground));
|
| 1793 |
+
}
|
| 1794 |
+
|
| 1795 |
+
.text-foreground {
|
| 1796 |
+
color: hsl(var(--foreground));
|
| 1797 |
+
}
|
| 1798 |
+
|
| 1799 |
+
.text-foreground\/50 {
|
| 1800 |
+
color: hsl(var(--foreground) / 0.5);
|
| 1801 |
+
}
|
| 1802 |
+
|
| 1803 |
+
.text-gray-800 {
|
| 1804 |
+
--tw-text-opacity: 1;
|
| 1805 |
+
color: rgb(31 41 55 / var(--tw-text-opacity));
|
| 1806 |
+
}
|
| 1807 |
+
|
| 1808 |
+
.text-gray-900 {
|
| 1809 |
+
--tw-text-opacity: 1;
|
| 1810 |
+
color: rgb(17 24 39 / var(--tw-text-opacity));
|
| 1811 |
+
}
|
| 1812 |
+
|
| 1813 |
+
.text-muted-foreground {
|
| 1814 |
+
color: hsl(var(--muted-foreground));
|
| 1815 |
+
}
|
| 1816 |
+
|
| 1817 |
+
.text-popover-foreground {
|
| 1818 |
+
color: hsl(var(--popover-foreground));
|
| 1819 |
+
}
|
| 1820 |
+
|
| 1821 |
+
.text-primary {
|
| 1822 |
+
color: hsl(var(--primary));
|
| 1823 |
+
}
|
| 1824 |
+
|
| 1825 |
+
.text-primary-foreground {
|
| 1826 |
+
color: hsl(var(--primary-foreground));
|
| 1827 |
+
}
|
| 1828 |
+
|
| 1829 |
+
.text-secondary-foreground {
|
| 1830 |
+
color: hsl(var(--secondary-foreground));
|
| 1831 |
+
}
|
| 1832 |
+
|
| 1833 |
+
.text-transparent {
|
| 1834 |
+
color: transparent;
|
| 1835 |
+
}
|
| 1836 |
+
|
| 1837 |
+
.text-white {
|
| 1838 |
+
--tw-text-opacity: 1;
|
| 1839 |
+
color: rgb(255 255 255 / var(--tw-text-opacity));
|
| 1840 |
+
}
|
| 1841 |
+
|
| 1842 |
+
.no-underline {
|
| 1843 |
+
text-decoration-line: none;
|
| 1844 |
+
}
|
| 1845 |
+
|
| 1846 |
+
.underline-offset-4 {
|
| 1847 |
+
text-underline-offset: 4px;
|
| 1848 |
+
}
|
| 1849 |
+
|
| 1850 |
+
.antialiased {
|
| 1851 |
+
-webkit-font-smoothing: antialiased;
|
| 1852 |
+
-moz-osx-font-smoothing: grayscale;
|
| 1853 |
+
}
|
| 1854 |
+
|
| 1855 |
+
.opacity-0 {
|
| 1856 |
+
opacity: 0;
|
| 1857 |
+
}
|
| 1858 |
+
|
| 1859 |
+
.opacity-50 {
|
| 1860 |
+
opacity: 0.5;
|
| 1861 |
+
}
|
| 1862 |
+
|
| 1863 |
+
.opacity-70 {
|
| 1864 |
+
opacity: 0.7;
|
| 1865 |
+
}
|
| 1866 |
+
|
| 1867 |
+
.opacity-90 {
|
| 1868 |
+
opacity: 0.9;
|
| 1869 |
+
}
|
| 1870 |
+
|
| 1871 |
+
.shadow-lg {
|
| 1872 |
+
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
| 1873 |
+
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
| 1874 |
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
| 1875 |
+
}
|
| 1876 |
+
|
| 1877 |
+
.shadow-md {
|
| 1878 |
+
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
| 1879 |
+
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
| 1880 |
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
| 1881 |
+
}
|
| 1882 |
+
|
| 1883 |
+
.shadow-sm {
|
| 1884 |
+
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
| 1885 |
+
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
| 1886 |
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
| 1887 |
+
}
|
| 1888 |
+
|
| 1889 |
+
.outline-none {
|
| 1890 |
+
outline: 2px solid transparent;
|
| 1891 |
+
outline-offset: 2px;
|
| 1892 |
+
}
|
| 1893 |
+
|
| 1894 |
+
.outline {
|
| 1895 |
+
outline-style: solid;
|
| 1896 |
+
}
|
| 1897 |
+
|
| 1898 |
+
.ring {
|
| 1899 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 1900 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 1901 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 1902 |
+
}
|
| 1903 |
+
|
| 1904 |
+
.ring-0 {
|
| 1905 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 1906 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 1907 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 1908 |
+
}
|
| 1909 |
+
|
| 1910 |
+
.ring-1 {
|
| 1911 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 1912 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 1913 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 1914 |
+
}
|
| 1915 |
+
|
| 1916 |
+
.ring-black {
|
| 1917 |
+
--tw-ring-opacity: 1;
|
| 1918 |
+
--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
|
| 1919 |
+
}
|
| 1920 |
+
|
| 1921 |
+
.ring-opacity-5 {
|
| 1922 |
+
--tw-ring-opacity: 0.05;
|
| 1923 |
+
}
|
| 1924 |
+
|
| 1925 |
+
.ring-offset-background {
|
| 1926 |
+
--tw-ring-offset-color: hsl(var(--background));
|
| 1927 |
+
}
|
| 1928 |
+
|
| 1929 |
+
.ring-offset-transparent {
|
| 1930 |
+
--tw-ring-offset-color: transparent;
|
| 1931 |
+
}
|
| 1932 |
+
|
| 1933 |
+
.blur {
|
| 1934 |
+
--tw-blur: blur(8px);
|
| 1935 |
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
| 1936 |
+
}
|
| 1937 |
+
|
| 1938 |
+
.filter {
|
| 1939 |
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
| 1940 |
+
}
|
| 1941 |
+
|
| 1942 |
+
.backdrop-filter {
|
| 1943 |
+
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
| 1944 |
+
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
| 1945 |
+
}
|
| 1946 |
+
|
| 1947 |
+
.transition {
|
| 1948 |
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
| 1949 |
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
| 1950 |
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
| 1951 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1952 |
+
transition-duration: 150ms;
|
| 1953 |
+
}
|
| 1954 |
+
|
| 1955 |
+
.transition-all {
|
| 1956 |
+
transition-property: all;
|
| 1957 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1958 |
+
transition-duration: 150ms;
|
| 1959 |
+
}
|
| 1960 |
+
|
| 1961 |
+
.transition-colors {
|
| 1962 |
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
| 1963 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1964 |
+
transition-duration: 150ms;
|
| 1965 |
+
}
|
| 1966 |
+
|
| 1967 |
+
.transition-opacity {
|
| 1968 |
+
transition-property: opacity;
|
| 1969 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1970 |
+
transition-duration: 150ms;
|
| 1971 |
+
}
|
| 1972 |
+
|
| 1973 |
+
.transition-transform {
|
| 1974 |
+
transition-property: transform;
|
| 1975 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1976 |
+
transition-duration: 150ms;
|
| 1977 |
+
}
|
| 1978 |
+
|
| 1979 |
+
.duration-200 {
|
| 1980 |
+
transition-duration: 200ms;
|
| 1981 |
+
}
|
| 1982 |
+
|
| 1983 |
+
.duration-300 {
|
| 1984 |
+
transition-duration: 300ms;
|
| 1985 |
+
}
|
| 1986 |
+
|
| 1987 |
+
.ease-in-out {
|
| 1988 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 1989 |
+
}
|
| 1990 |
+
|
| 1991 |
+
.ease-out {
|
| 1992 |
+
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
| 1993 |
+
}
|
| 1994 |
+
|
| 1995 |
+
@keyframes enter {
|
| 1996 |
+
from {
|
| 1997 |
+
opacity: var(--tw-enter-opacity, 1);
|
| 1998 |
+
transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0));
|
| 1999 |
+
}
|
| 2000 |
+
}
|
| 2001 |
+
|
| 2002 |
+
@keyframes exit {
|
| 2003 |
+
to {
|
| 2004 |
+
opacity: var(--tw-exit-opacity, 1);
|
| 2005 |
+
transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0));
|
| 2006 |
+
}
|
| 2007 |
+
}
|
| 2008 |
+
|
| 2009 |
+
.animate-in {
|
| 2010 |
+
animation-name: enter;
|
| 2011 |
+
animation-duration: 150ms;
|
| 2012 |
+
--tw-enter-opacity: initial;
|
| 2013 |
+
--tw-enter-scale: initial;
|
| 2014 |
+
--tw-enter-rotate: initial;
|
| 2015 |
+
--tw-enter-translate-x: initial;
|
| 2016 |
+
--tw-enter-translate-y: initial;
|
| 2017 |
+
}
|
| 2018 |
+
|
| 2019 |
+
.animate-out {
|
| 2020 |
+
animation-name: exit;
|
| 2021 |
+
animation-duration: 150ms;
|
| 2022 |
+
--tw-exit-opacity: initial;
|
| 2023 |
+
--tw-exit-scale: initial;
|
| 2024 |
+
--tw-exit-rotate: initial;
|
| 2025 |
+
--tw-exit-translate-x: initial;
|
| 2026 |
+
--tw-exit-translate-y: initial;
|
| 2027 |
+
}
|
| 2028 |
+
|
| 2029 |
+
.fade-in {
|
| 2030 |
+
--tw-enter-opacity: 0;
|
| 2031 |
+
}
|
| 2032 |
+
|
| 2033 |
+
.fade-out {
|
| 2034 |
+
--tw-exit-opacity: 0;
|
| 2035 |
+
}
|
| 2036 |
+
|
| 2037 |
+
.zoom-in {
|
| 2038 |
+
--tw-enter-scale: 0;
|
| 2039 |
+
}
|
| 2040 |
+
|
| 2041 |
+
.zoom-out {
|
| 2042 |
+
--tw-exit-scale: 0;
|
| 2043 |
+
}
|
| 2044 |
+
|
| 2045 |
+
.spin-in {
|
| 2046 |
+
--tw-enter-rotate: 30deg;
|
| 2047 |
+
}
|
| 2048 |
+
|
| 2049 |
+
.spin-out {
|
| 2050 |
+
--tw-exit-rotate: 30deg;
|
| 2051 |
+
}
|
| 2052 |
+
|
| 2053 |
+
.slide-in-from-bottom {
|
| 2054 |
+
--tw-enter-translate-y: 100%;
|
| 2055 |
+
}
|
| 2056 |
+
|
| 2057 |
+
.slide-in-from-bottom-2 {
|
| 2058 |
+
--tw-enter-translate-y: 0.5rem;
|
| 2059 |
+
}
|
| 2060 |
+
|
| 2061 |
+
.slide-in-from-left {
|
| 2062 |
+
--tw-enter-translate-x: -100%;
|
| 2063 |
+
}
|
| 2064 |
+
|
| 2065 |
+
.slide-in-from-right {
|
| 2066 |
+
--tw-enter-translate-x: 100%;
|
| 2067 |
+
}
|
| 2068 |
+
|
| 2069 |
+
.slide-in-from-top {
|
| 2070 |
+
--tw-enter-translate-y: -100%;
|
| 2071 |
+
}
|
| 2072 |
+
|
| 2073 |
+
.slide-in-from-top-2 {
|
| 2074 |
+
--tw-enter-translate-y: -0.5rem;
|
| 2075 |
+
}
|
| 2076 |
+
|
| 2077 |
+
.slide-out-to-bottom {
|
| 2078 |
+
--tw-exit-translate-y: 100%;
|
| 2079 |
+
}
|
| 2080 |
+
|
| 2081 |
+
.slide-out-to-left {
|
| 2082 |
+
--tw-exit-translate-x: -100%;
|
| 2083 |
+
}
|
| 2084 |
+
|
| 2085 |
+
.slide-out-to-right {
|
| 2086 |
+
--tw-exit-translate-x: 100%;
|
| 2087 |
+
}
|
| 2088 |
+
|
| 2089 |
+
.slide-out-to-top {
|
| 2090 |
+
--tw-exit-translate-y: -100%;
|
| 2091 |
+
}
|
| 2092 |
+
|
| 2093 |
+
.duration-200 {
|
| 2094 |
+
animation-duration: 200ms;
|
| 2095 |
+
}
|
| 2096 |
+
|
| 2097 |
+
.duration-300 {
|
| 2098 |
+
animation-duration: 300ms;
|
| 2099 |
+
}
|
| 2100 |
+
|
| 2101 |
+
.ease-in-out {
|
| 2102 |
+
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
| 2103 |
+
}
|
| 2104 |
+
|
| 2105 |
+
.ease-out {
|
| 2106 |
+
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
| 2107 |
+
}
|
| 2108 |
+
|
| 2109 |
+
.running {
|
| 2110 |
+
animation-play-state: running;
|
| 2111 |
+
}
|
| 2112 |
+
|
| 2113 |
+
.paused {
|
| 2114 |
+
animation-play-state: paused;
|
| 2115 |
+
}
|
| 2116 |
+
|
| 2117 |
+
/* Hide scrollbar for Chrome, Safari and Opera */
|
| 2118 |
+
|
| 2119 |
+
.no-scrollbar::-webkit-scrollbar {
|
| 2120 |
+
display: none;
|
| 2121 |
+
}
|
| 2122 |
+
|
| 2123 |
+
/* Hide scrollbar for IE, Edge and Firefox */
|
| 2124 |
+
|
| 2125 |
+
.no-scrollbar {
|
| 2126 |
+
-webkit-overflow-scrolling: touch;
|
| 2127 |
+
-ms-overflow-style: none;
|
| 2128 |
+
/* IE and Edge */
|
| 2129 |
+
scrollbar-width: none;
|
| 2130 |
+
/* Firefox */
|
| 2131 |
+
}
|
| 2132 |
+
|
| 2133 |
+
@keyframes slideInFromTop {
|
| 2134 |
+
from {
|
| 2135 |
+
transform: translateY(-100%);
|
| 2136 |
+
}
|
| 2137 |
+
|
| 2138 |
+
to {
|
| 2139 |
+
transform: translateY(0);
|
| 2140 |
+
}
|
| 2141 |
+
}
|
| 2142 |
+
|
| 2143 |
+
@keyframes slideInFromBottom {
|
| 2144 |
+
from {
|
| 2145 |
+
transform: translateY(100%);
|
| 2146 |
+
}
|
| 2147 |
+
|
| 2148 |
+
to {
|
| 2149 |
+
transform: translateY(0);
|
| 2150 |
+
}
|
| 2151 |
+
}
|
| 2152 |
+
|
| 2153 |
+
.toast {
|
| 2154 |
+
animation-duration: 0.2s;
|
| 2155 |
+
animation-fill-mode: forwards;
|
| 2156 |
+
}
|
| 2157 |
+
|
| 2158 |
+
@media (max-width: 640px) {
|
| 2159 |
+
.toast {
|
| 2160 |
+
animation-name: slideInFromTop;
|
| 2161 |
+
}
|
| 2162 |
+
}
|
| 2163 |
+
|
| 2164 |
+
@media (min-width: 641px) {
|
| 2165 |
+
.toast {
|
| 2166 |
+
animation-name: slideInFromBottom;
|
| 2167 |
+
}
|
| 2168 |
+
}
|
| 2169 |
+
|
| 2170 |
+
@keyframes fade-in {
|
| 2171 |
+
from {
|
| 2172 |
+
opacity: 0;
|
| 2173 |
+
}
|
| 2174 |
+
|
| 2175 |
+
to {
|
| 2176 |
+
opacity: 1;
|
| 2177 |
+
}
|
| 2178 |
+
}
|
| 2179 |
+
|
| 2180 |
+
@keyframes slide-up {
|
| 2181 |
+
from {
|
| 2182 |
+
transform: translateY(20px);
|
| 2183 |
+
opacity: 0;
|
| 2184 |
+
}
|
| 2185 |
+
|
| 2186 |
+
to {
|
| 2187 |
+
transform: translateY(0);
|
| 2188 |
+
opacity: 1;
|
| 2189 |
+
}
|
| 2190 |
+
}
|
| 2191 |
+
|
| 2192 |
+
.animate-fade-in {
|
| 2193 |
+
animation: fade-in 1s ease-out forwards;
|
| 2194 |
+
}
|
| 2195 |
+
|
| 2196 |
+
.animate-slide-up {
|
| 2197 |
+
animation: slide-up 1s ease-out forwards;
|
| 2198 |
+
}
|
| 2199 |
+
|
| 2200 |
+
.sim-map-button.active {
|
| 2201 |
+
background-color: #61D790;
|
| 2202 |
+
color: #2E2F27;
|
| 2203 |
+
&:hover {
|
| 2204 |
+
background-color: #61D790;
|
| 2205 |
+
}
|
| 2206 |
+
}
|
| 2207 |
+
|
| 2208 |
+
.text-highlight strong {
|
| 2209 |
+
color: black;
|
| 2210 |
+
.dark & {
|
| 2211 |
+
color: white;
|
| 2212 |
+
}
|
| 2213 |
+
}
|
| 2214 |
+
|
| 2215 |
+
.tokens-button {
|
| 2216 |
+
background-color: #B7E2F1;
|
| 2217 |
+
color: #2E2F27;
|
| 2218 |
+
}
|
| 2219 |
+
|
| 2220 |
+
.overlay-image {
|
| 2221 |
+
opacity: 0.5;
|
| 2222 |
+
position: absolute;
|
| 2223 |
+
top: 0;
|
| 2224 |
+
left: 0;
|
| 2225 |
+
width: 100%;
|
| 2226 |
+
height: 100%;
|
| 2227 |
+
z-index: 10;
|
| 2228 |
+
}
|
| 2229 |
+
|
| 2230 |
+
header {
|
| 2231 |
+
grid-column: 1/-1;
|
| 2232 |
+
}
|
| 2233 |
+
|
| 2234 |
+
body {
|
| 2235 |
+
&[data-is-home="true"] {
|
| 2236 |
+
background: radial-gradient(circle at 50% 100%, #fcfcfd, #fcfcfd, #fdfdfe, #fdfdfe, #fefefe, #fefefe, #ffffff, #ffffff);
|
| 2237 |
+
.dark & {
|
| 2238 |
+
background: radial-gradient(circle at 50% 50%, #272a2d, #242629, #212326, #1e1f22, #1b1c1e, #18181b, #151517, #111113);
|
| 2239 |
+
}
|
| 2240 |
+
}
|
| 2241 |
+
}
|
| 2242 |
+
|
| 2243 |
+
main {
|
| 2244 |
+
overflow: auto;
|
| 2245 |
+
}
|
| 2246 |
+
|
| 2247 |
+
aside {
|
| 2248 |
+
overflow: auto;
|
| 2249 |
+
}
|
| 2250 |
+
|
| 2251 |
+
.scroll-container {
|
| 2252 |
+
padding-right: 10px;
|
| 2253 |
+
}
|
| 2254 |
+
|
| 2255 |
+
.question-message {
|
| 2256 |
+
background-color: #61D790;
|
| 2257 |
+
color: #2E2F27;
|
| 2258 |
+
}
|
| 2259 |
+
|
| 2260 |
+
@media (min-width: 768px) {
|
| 2261 |
+
.grid-image-text-columns {
|
| 2262 |
+
grid-column: span 2 / span 2;
|
| 2263 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 2264 |
+
}
|
| 2265 |
+
}
|
| 2266 |
+
|
| 2267 |
+
.grid-image-column {
|
| 2268 |
+
grid-row: span 2 / span 2;
|
| 2269 |
+
display: grid;
|
| 2270 |
+
grid-template-rows: subgrid;
|
| 2271 |
+
align-content: flex-start;
|
| 2272 |
+
}
|
| 2273 |
+
|
| 2274 |
+
@media (min-width: 768px) {
|
| 2275 |
+
.md-grid-text-column {
|
| 2276 |
+
grid-row: span 2 / span 2;
|
| 2277 |
+
display: grid;
|
| 2278 |
+
grid-template-rows: subgrid;
|
| 2279 |
+
align-content: flex-start;
|
| 2280 |
+
}
|
| 2281 |
+
}
|
| 2282 |
+
|
| 2283 |
+
#search-input[aria-expanded="true"] {
|
| 2284 |
+
border-top: 1px solid hsl(var(--input));
|
| 2285 |
+
border-left: 1px solid hsl(var(--input));
|
| 2286 |
+
border-right: 1px solid hsl(var(--input));
|
| 2287 |
+
border-bottom: none;
|
| 2288 |
+
border-bottom-left-radius: 0;
|
| 2289 |
+
border-bottom-right-radius: 0;
|
| 2290 |
+
}
|
| 2291 |
+
|
| 2292 |
+
.awesomplete {
|
| 2293 |
+
width: 100%;
|
| 2294 |
+
}
|
| 2295 |
+
|
| 2296 |
+
.awesomplete > ul > :not([hidden]) ~ :not([hidden]) {
|
| 2297 |
+
--tw-space-y-reverse: 0;
|
| 2298 |
+
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
|
| 2299 |
+
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
| 2300 |
+
}
|
| 2301 |
+
|
| 2302 |
+
.awesomplete > ul {
|
| 2303 |
+
font-size: 0.875rem;
|
| 2304 |
+
line-height: 1.25rem;
|
| 2305 |
+
margin: 0;
|
| 2306 |
+
border-top: none;
|
| 2307 |
+
border-left: 1px solid hsl(var(--input));
|
| 2308 |
+
border-right: 1px solid hsl(var(--input));
|
| 2309 |
+
border-bottom: 1px solid hsl(var(--input));
|
| 2310 |
+
border-radius: 0 0 calc(var(--radius) - 2px) calc(var(--radius) - 2px);
|
| 2311 |
+
background: white;
|
| 2312 |
+
.dark & {
|
| 2313 |
+
background: hsl(var(--background));
|
| 2314 |
+
}
|
| 2315 |
+
box-shadow: none;
|
| 2316 |
+
text-shadow: none;
|
| 2317 |
+
}
|
| 2318 |
+
|
| 2319 |
+
.awesomplete > ul:before {
|
| 2320 |
+
display: none;
|
| 2321 |
+
}
|
| 2322 |
+
|
| 2323 |
+
.awesomplete > ul > li:hover {
|
| 2324 |
+
background-color: #B7E2F1;
|
| 2325 |
+
color: #2E2F27;
|
| 2326 |
+
}
|
| 2327 |
+
|
| 2328 |
+
.awesomplete > ul > li[aria-selected="true"] {
|
| 2329 |
+
background-color: #B7E2F1;
|
| 2330 |
+
color: #2E2F27;
|
| 2331 |
+
}
|
| 2332 |
+
|
| 2333 |
+
.awesomplete mark {
|
| 2334 |
+
background-color: #61D790;
|
| 2335 |
+
color: #2E2F27;
|
| 2336 |
+
}
|
| 2337 |
+
|
| 2338 |
+
.awesomplete li:hover mark {
|
| 2339 |
+
background-color: #61D790;
|
| 2340 |
+
color: #2E2F27;
|
| 2341 |
+
}
|
| 2342 |
+
|
| 2343 |
+
.awesomplete li[aria-selected="true"] mark {
|
| 2344 |
+
background-color: #61D790;
|
| 2345 |
+
color: #2E2F27;
|
| 2346 |
+
}
|
| 2347 |
+
|
| 2348 |
+
:root:has(.data-\[state\=open\]\:no-bg-scroll[data-state="open"]) {
|
| 2349 |
+
overflow: hidden;
|
| 2350 |
+
}
|
| 2351 |
+
|
| 2352 |
+
:root:has(.group[data-state="open"] .group-data-\[state\=open\]\:no-bg-scroll) {
|
| 2353 |
+
overflow: hidden;
|
| 2354 |
+
}
|
| 2355 |
+
|
| 2356 |
+
.file\:border-0::file-selector-button {
|
| 2357 |
+
border-width: 0px;
|
| 2358 |
+
}
|
| 2359 |
+
|
| 2360 |
+
.file\:bg-transparent::file-selector-button {
|
| 2361 |
+
background-color: transparent;
|
| 2362 |
+
}
|
| 2363 |
+
|
| 2364 |
+
.file\:text-sm::file-selector-button {
|
| 2365 |
+
font-size: 0.875rem;
|
| 2366 |
+
line-height: 1.25rem;
|
| 2367 |
+
}
|
| 2368 |
+
|
| 2369 |
+
.file\:font-medium::file-selector-button {
|
| 2370 |
+
font-weight: 500;
|
| 2371 |
+
}
|
| 2372 |
+
|
| 2373 |
+
.placeholder\:text-muted-foreground::-moz-placeholder {
|
| 2374 |
+
color: hsl(var(--muted-foreground));
|
| 2375 |
+
}
|
| 2376 |
+
|
| 2377 |
+
.placeholder\:text-muted-foreground::placeholder {
|
| 2378 |
+
color: hsl(var(--muted-foreground));
|
| 2379 |
+
}
|
| 2380 |
+
|
| 2381 |
+
.focus-within\:border-input:focus-within {
|
| 2382 |
+
border-color: hsl(var(--input));
|
| 2383 |
+
}
|
| 2384 |
+
|
| 2385 |
+
.focus-within\:outline-none:focus-within {
|
| 2386 |
+
outline: 2px solid transparent;
|
| 2387 |
+
outline-offset: 2px;
|
| 2388 |
+
}
|
| 2389 |
+
|
| 2390 |
+
.focus-within\:ring-2:focus-within {
|
| 2391 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 2392 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 2393 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 2394 |
+
}
|
| 2395 |
+
|
| 2396 |
+
.focus-within\:ring-ring:focus-within {
|
| 2397 |
+
--tw-ring-color: hsl(var(--ring));
|
| 2398 |
+
}
|
| 2399 |
+
|
| 2400 |
+
.focus-within\:ring-offset-2:focus-within {
|
| 2401 |
+
--tw-ring-offset-width: 2px;
|
| 2402 |
+
}
|
| 2403 |
+
|
| 2404 |
+
.hover\:border-black:hover {
|
| 2405 |
+
--tw-border-opacity: 1;
|
| 2406 |
+
border-color: rgb(0 0 0 / var(--tw-border-opacity));
|
| 2407 |
+
}
|
| 2408 |
+
|
| 2409 |
+
.hover\:bg-accent:hover {
|
| 2410 |
+
background-color: hsl(var(--accent));
|
| 2411 |
+
}
|
| 2412 |
+
|
| 2413 |
+
.hover\:bg-destructive\/80:hover {
|
| 2414 |
+
background-color: hsl(var(--destructive) / 0.8);
|
| 2415 |
+
}
|
| 2416 |
+
|
| 2417 |
+
.hover\:bg-destructive\/90:hover {
|
| 2418 |
+
background-color: hsl(var(--destructive) / 0.9);
|
| 2419 |
+
}
|
| 2420 |
+
|
| 2421 |
+
.hover\:bg-muted\/50:hover {
|
| 2422 |
+
background-color: hsl(var(--muted) / 0.5);
|
| 2423 |
+
}
|
| 2424 |
+
|
| 2425 |
+
.hover\:bg-primary\/80:hover {
|
| 2426 |
+
background-color: hsl(var(--primary) / 0.8);
|
| 2427 |
+
}
|
| 2428 |
+
|
| 2429 |
+
.hover\:bg-primary\/90:hover {
|
| 2430 |
+
background-color: hsl(var(--primary) / 0.9);
|
| 2431 |
+
}
|
| 2432 |
+
|
| 2433 |
+
.hover\:bg-secondary\/80:hover {
|
| 2434 |
+
background-color: hsl(var(--secondary) / 0.8);
|
| 2435 |
+
}
|
| 2436 |
+
|
| 2437 |
+
.hover\:text-accent-foreground:hover {
|
| 2438 |
+
color: hsl(var(--accent-foreground));
|
| 2439 |
+
}
|
| 2440 |
+
|
| 2441 |
+
.hover\:text-foreground:hover {
|
| 2442 |
+
color: hsl(var(--foreground));
|
| 2443 |
+
}
|
| 2444 |
+
|
| 2445 |
+
.hover\:text-primary:hover {
|
| 2446 |
+
color: hsl(var(--primary));
|
| 2447 |
+
}
|
| 2448 |
+
|
| 2449 |
+
.hover\:underline:hover {
|
| 2450 |
+
text-decoration-line: underline;
|
| 2451 |
+
}
|
| 2452 |
+
|
| 2453 |
+
.hover\:opacity-100:hover {
|
| 2454 |
+
opacity: 1;
|
| 2455 |
+
}
|
| 2456 |
+
|
| 2457 |
+
.focus\:bg-accent:focus {
|
| 2458 |
+
background-color: hsl(var(--accent));
|
| 2459 |
+
}
|
| 2460 |
+
|
| 2461 |
+
.focus\:text-accent-foreground:focus {
|
| 2462 |
+
color: hsl(var(--accent-foreground));
|
| 2463 |
+
}
|
| 2464 |
+
|
| 2465 |
+
.focus\:opacity-100:focus {
|
| 2466 |
+
opacity: 1;
|
| 2467 |
+
}
|
| 2468 |
+
|
| 2469 |
+
.focus\:outline-none:focus {
|
| 2470 |
+
outline: 2px solid transparent;
|
| 2471 |
+
outline-offset: 2px;
|
| 2472 |
+
}
|
| 2473 |
+
|
| 2474 |
+
.focus\:ring-2:focus {
|
| 2475 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 2476 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 2477 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 2478 |
+
}
|
| 2479 |
+
|
| 2480 |
+
.focus\:ring-ring:focus {
|
| 2481 |
+
--tw-ring-color: hsl(var(--ring));
|
| 2482 |
+
}
|
| 2483 |
+
|
| 2484 |
+
.focus\:ring-offset-2:focus {
|
| 2485 |
+
--tw-ring-offset-width: 2px;
|
| 2486 |
+
}
|
| 2487 |
+
|
| 2488 |
+
.focus-visible\:outline-none:focus-visible {
|
| 2489 |
+
outline: 2px solid transparent;
|
| 2490 |
+
outline-offset: 2px;
|
| 2491 |
+
}
|
| 2492 |
+
|
| 2493 |
+
.focus-visible\:ring-2:focus-visible {
|
| 2494 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 2495 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 2496 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 2497 |
+
}
|
| 2498 |
+
|
| 2499 |
+
.focus-visible\:ring-ring:focus-visible {
|
| 2500 |
+
--tw-ring-color: hsl(var(--ring));
|
| 2501 |
+
}
|
| 2502 |
+
|
| 2503 |
+
.focus-visible\:ring-transparent:focus-visible {
|
| 2504 |
+
--tw-ring-color: transparent;
|
| 2505 |
+
}
|
| 2506 |
+
|
| 2507 |
+
.focus-visible\:ring-offset-2:focus-visible {
|
| 2508 |
+
--tw-ring-offset-width: 2px;
|
| 2509 |
+
}
|
| 2510 |
+
|
| 2511 |
+
.active\:ring:active {
|
| 2512 |
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
| 2513 |
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
| 2514 |
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
| 2515 |
+
}
|
| 2516 |
+
|
| 2517 |
+
.disabled\:pointer-events-none:disabled {
|
| 2518 |
+
pointer-events: none;
|
| 2519 |
+
}
|
| 2520 |
+
|
| 2521 |
+
.disabled\:cursor-not-allowed:disabled {
|
| 2522 |
+
cursor: not-allowed;
|
| 2523 |
+
}
|
| 2524 |
+
|
| 2525 |
+
.disabled\:opacity-50:disabled {
|
| 2526 |
+
opacity: 0.5;
|
| 2527 |
+
}
|
| 2528 |
+
|
| 2529 |
+
.group:hover .group-hover\:opacity-100 {
|
| 2530 |
+
opacity: 1;
|
| 2531 |
+
}
|
| 2532 |
+
|
| 2533 |
+
.group.destructive .group-\[\.destructive\]\:text-red-300 {
|
| 2534 |
+
--tw-text-opacity: 1;
|
| 2535 |
+
color: rgb(252 165 165 / var(--tw-text-opacity));
|
| 2536 |
+
}
|
| 2537 |
+
|
| 2538 |
+
.group.destructive .group-\[\.destructive\]\:hover\:text-red-50:hover {
|
| 2539 |
+
--tw-text-opacity: 1;
|
| 2540 |
+
color: rgb(254 242 242 / var(--tw-text-opacity));
|
| 2541 |
+
}
|
| 2542 |
+
|
| 2543 |
+
.group.destructive .group-\[\.destructive\]\:focus\:ring-red-400:focus {
|
| 2544 |
+
--tw-ring-opacity: 1;
|
| 2545 |
+
--tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity));
|
| 2546 |
+
}
|
| 2547 |
+
|
| 2548 |
+
.group.destructive .group-\[\.destructive\]\:focus\:ring-offset-red-600:focus {
|
| 2549 |
+
--tw-ring-offset-color: #dc2626;
|
| 2550 |
+
}
|
| 2551 |
+
|
| 2552 |
+
.peer:checked ~ .peer-checked\:bg-primary {
|
| 2553 |
+
background-color: hsl(var(--primary));
|
| 2554 |
+
}
|
| 2555 |
+
|
| 2556 |
+
.peer:checked ~ .peer-checked\:text-primary-foreground {
|
| 2557 |
+
color: hsl(var(--primary-foreground));
|
| 2558 |
+
}
|
| 2559 |
+
|
| 2560 |
+
.peer:disabled ~ .peer-disabled\:cursor-not-allowed {
|
| 2561 |
+
cursor: not-allowed;
|
| 2562 |
+
}
|
| 2563 |
+
|
| 2564 |
+
.peer:disabled ~ .peer-disabled\:opacity-50 {
|
| 2565 |
+
opacity: 0.5;
|
| 2566 |
+
}
|
| 2567 |
+
|
| 2568 |
+
.peer:disabled ~ .peer-disabled\:opacity-70 {
|
| 2569 |
+
opacity: 0.7;
|
| 2570 |
+
}
|
| 2571 |
+
|
| 2572 |
+
.data-\[disabled\]\:pointer-events-none[data-disabled] {
|
| 2573 |
+
pointer-events: none;
|
| 2574 |
+
}
|
| 2575 |
+
|
| 2576 |
+
.data-\[state\=active\]\:bg-background[data-state="active"] {
|
| 2577 |
+
background-color: hsl(var(--background));
|
| 2578 |
+
}
|
| 2579 |
+
|
| 2580 |
+
.data-\[state\=selected\]\:bg-muted[data-state="selected"] {
|
| 2581 |
+
background-color: hsl(var(--muted));
|
| 2582 |
+
}
|
| 2583 |
+
|
| 2584 |
+
.data-\[state\=active\]\:text-foreground[data-state="active"] {
|
| 2585 |
+
color: hsl(var(--foreground));
|
| 2586 |
+
}
|
| 2587 |
+
|
| 2588 |
+
.data-\[disabled\]\:opacity-50[data-disabled] {
|
| 2589 |
+
opacity: 0.5;
|
| 2590 |
+
}
|
| 2591 |
+
|
| 2592 |
+
.data-\[state\=active\]\:shadow-sm[data-state="active"] {
|
| 2593 |
+
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
| 2594 |
+
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
| 2595 |
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
| 2596 |
+
}
|
| 2597 |
+
|
| 2598 |
+
.data-\[state\=open\]\:animate-in[data-state="open"] {
|
| 2599 |
+
animation-name: enter;
|
| 2600 |
+
animation-duration: 150ms;
|
| 2601 |
+
--tw-enter-opacity: initial;
|
| 2602 |
+
--tw-enter-scale: initial;
|
| 2603 |
+
--tw-enter-rotate: initial;
|
| 2604 |
+
--tw-enter-translate-x: initial;
|
| 2605 |
+
--tw-enter-translate-y: initial;
|
| 2606 |
+
}
|
| 2607 |
+
|
| 2608 |
+
.data-\[state\=closed\]\:animate-out[data-state="closed"] {
|
| 2609 |
+
animation-name: exit;
|
| 2610 |
+
animation-duration: 150ms;
|
| 2611 |
+
--tw-exit-opacity: initial;
|
| 2612 |
+
--tw-exit-scale: initial;
|
| 2613 |
+
--tw-exit-rotate: initial;
|
| 2614 |
+
--tw-exit-translate-x: initial;
|
| 2615 |
+
--tw-exit-translate-y: initial;
|
| 2616 |
+
}
|
| 2617 |
+
|
| 2618 |
+
.data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
|
| 2619 |
+
--tw-exit-opacity: 0;
|
| 2620 |
+
}
|
| 2621 |
+
|
| 2622 |
+
.data-\[state\=open\]\:fade-in-0[data-state="open"] {
|
| 2623 |
+
--tw-enter-opacity: 0;
|
| 2624 |
+
}
|
| 2625 |
+
|
| 2626 |
+
.data-\[popper-placement\=\'bottom-start\'\]\:slide-in-from-top-2[data-popper-placement='bottom-start'] {
|
| 2627 |
+
--tw-enter-translate-y: -0.5rem;
|
| 2628 |
+
}
|
| 2629 |
+
|
| 2630 |
+
.data-\[popper-placement\=\'top-start\'\]\:slide-in-from-bottom-2[data-popper-placement='top-start'] {
|
| 2631 |
+
--tw-enter-translate-y: 0.5rem;
|
| 2632 |
+
}
|
| 2633 |
+
|
| 2634 |
+
.group[data-checked="true"] .group-data-\[checked\=true\]\:flex {
|
| 2635 |
+
display: flex;
|
| 2636 |
+
}
|
| 2637 |
+
|
| 2638 |
+
.group[data-state="checked"] .group-data-\[state\=checked\]\:flex {
|
| 2639 |
+
display: flex;
|
| 2640 |
+
}
|
| 2641 |
+
|
| 2642 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:rotate-180 {
|
| 2643 |
+
--tw-rotate: 180deg;
|
| 2644 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 2645 |
+
}
|
| 2646 |
+
|
| 2647 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:duration-300 {
|
| 2648 |
+
transition-duration: 300ms;
|
| 2649 |
+
}
|
| 2650 |
+
|
| 2651 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:duration-500 {
|
| 2652 |
+
transition-duration: 500ms;
|
| 2653 |
+
}
|
| 2654 |
+
|
| 2655 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:animate-in {
|
| 2656 |
+
animation-name: enter;
|
| 2657 |
+
animation-duration: 150ms;
|
| 2658 |
+
--tw-enter-opacity: initial;
|
| 2659 |
+
--tw-enter-scale: initial;
|
| 2660 |
+
--tw-enter-rotate: initial;
|
| 2661 |
+
--tw-enter-translate-x: initial;
|
| 2662 |
+
--tw-enter-translate-y: initial;
|
| 2663 |
+
}
|
| 2664 |
+
|
| 2665 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:animate-out {
|
| 2666 |
+
animation-name: exit;
|
| 2667 |
+
animation-duration: 150ms;
|
| 2668 |
+
--tw-exit-opacity: initial;
|
| 2669 |
+
--tw-exit-scale: initial;
|
| 2670 |
+
--tw-exit-rotate: initial;
|
| 2671 |
+
--tw-exit-translate-x: initial;
|
| 2672 |
+
--tw-exit-translate-y: initial;
|
| 2673 |
+
}
|
| 2674 |
+
|
| 2675 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:fade-out-0 {
|
| 2676 |
+
--tw-exit-opacity: 0;
|
| 2677 |
+
}
|
| 2678 |
+
|
| 2679 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:fade-in-0 {
|
| 2680 |
+
--tw-enter-opacity: 0;
|
| 2681 |
+
}
|
| 2682 |
+
|
| 2683 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:zoom-out-95 {
|
| 2684 |
+
--tw-exit-scale: .95;
|
| 2685 |
+
}
|
| 2686 |
+
|
| 2687 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:zoom-in-95 {
|
| 2688 |
+
--tw-enter-scale: .95;
|
| 2689 |
+
}
|
| 2690 |
+
|
| 2691 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-bottom {
|
| 2692 |
+
--tw-exit-translate-y: 100%;
|
| 2693 |
+
}
|
| 2694 |
+
|
| 2695 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-left {
|
| 2696 |
+
--tw-exit-translate-x: -100%;
|
| 2697 |
+
}
|
| 2698 |
+
|
| 2699 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-left-1\/2 {
|
| 2700 |
+
--tw-exit-translate-x: -50%;
|
| 2701 |
+
}
|
| 2702 |
+
|
| 2703 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-right {
|
| 2704 |
+
--tw-exit-translate-x: 100%;
|
| 2705 |
+
}
|
| 2706 |
+
|
| 2707 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-top {
|
| 2708 |
+
--tw-exit-translate-y: -100%;
|
| 2709 |
+
}
|
| 2710 |
+
|
| 2711 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:slide-out-to-top-\[48\%\] {
|
| 2712 |
+
--tw-exit-translate-y: -48%;
|
| 2713 |
+
}
|
| 2714 |
+
|
| 2715 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-bottom {
|
| 2716 |
+
--tw-enter-translate-y: 100%;
|
| 2717 |
+
}
|
| 2718 |
+
|
| 2719 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-left {
|
| 2720 |
+
--tw-enter-translate-x: -100%;
|
| 2721 |
+
}
|
| 2722 |
+
|
| 2723 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-left-1\/2 {
|
| 2724 |
+
--tw-enter-translate-x: -50%;
|
| 2725 |
+
}
|
| 2726 |
+
|
| 2727 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-right {
|
| 2728 |
+
--tw-enter-translate-x: 100%;
|
| 2729 |
+
}
|
| 2730 |
+
|
| 2731 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-top {
|
| 2732 |
+
--tw-enter-translate-y: -100%;
|
| 2733 |
+
}
|
| 2734 |
+
|
| 2735 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:slide-in-from-top-\[48\%\] {
|
| 2736 |
+
--tw-enter-translate-y: -48%;
|
| 2737 |
+
}
|
| 2738 |
+
|
| 2739 |
+
.group[data-state="closed"] .group-data-\[state\=closed\]\:duration-300 {
|
| 2740 |
+
animation-duration: 300ms;
|
| 2741 |
+
}
|
| 2742 |
+
|
| 2743 |
+
.group[data-state="open"] .group-data-\[state\=open\]\:duration-500 {
|
| 2744 |
+
animation-duration: 500ms;
|
| 2745 |
+
}
|
| 2746 |
+
|
| 2747 |
+
.peer[data-state="closed"] ~ .peer-data-\[state\=closed\]\:animate-accordion-up {
|
| 2748 |
+
animation: accordion-up 0.2s ease-out;
|
| 2749 |
+
}
|
| 2750 |
+
|
| 2751 |
+
.peer[data-state="open"] ~ .peer-data-\[state\=open\]\:animate-accordion-down {
|
| 2752 |
+
animation: accordion-down 0.2s ease-out;
|
| 2753 |
+
}
|
| 2754 |
+
|
| 2755 |
+
@media (min-width: 640px) {
|
| 2756 |
+
.sm\:bottom-0 {
|
| 2757 |
+
bottom: 0px;
|
| 2758 |
+
}
|
| 2759 |
+
|
| 2760 |
+
.sm\:right-0 {
|
| 2761 |
+
right: 0px;
|
| 2762 |
+
}
|
| 2763 |
+
|
| 2764 |
+
.sm\:top-auto {
|
| 2765 |
+
top: auto;
|
| 2766 |
+
}
|
| 2767 |
+
|
| 2768 |
+
.sm\:flex {
|
| 2769 |
+
display: flex;
|
| 2770 |
+
}
|
| 2771 |
+
|
| 2772 |
+
.sm\:max-w-sm {
|
| 2773 |
+
max-width: 24rem;
|
| 2774 |
+
}
|
| 2775 |
+
|
| 2776 |
+
.sm\:flex-row {
|
| 2777 |
+
flex-direction: row;
|
| 2778 |
+
}
|
| 2779 |
+
|
| 2780 |
+
.sm\:flex-col {
|
| 2781 |
+
flex-direction: column;
|
| 2782 |
+
}
|
| 2783 |
+
|
| 2784 |
+
.sm\:justify-end {
|
| 2785 |
+
justify-content: flex-end;
|
| 2786 |
+
}
|
| 2787 |
+
|
| 2788 |
+
.sm\:gap-2\.5 {
|
| 2789 |
+
gap: 0.625rem;
|
| 2790 |
+
}
|
| 2791 |
+
|
| 2792 |
+
.sm\:space-x-2 > :not([hidden]) ~ :not([hidden]) {
|
| 2793 |
+
--tw-space-x-reverse: 0;
|
| 2794 |
+
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
| 2795 |
+
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
| 2796 |
+
}
|
| 2797 |
+
|
| 2798 |
+
.sm\:rounded-lg {
|
| 2799 |
+
border-radius: var(--radius);
|
| 2800 |
+
}
|
| 2801 |
+
|
| 2802 |
+
.sm\:text-left {
|
| 2803 |
+
text-align: left;
|
| 2804 |
+
}
|
| 2805 |
+
}
|
| 2806 |
+
|
| 2807 |
+
@media (min-width: 768px) {
|
| 2808 |
+
.md\:block {
|
| 2809 |
+
display: block;
|
| 2810 |
+
}
|
| 2811 |
+
|
| 2812 |
+
.md\:max-w-\[420px\] {
|
| 2813 |
+
max-width: 420px;
|
| 2814 |
+
}
|
| 2815 |
+
|
| 2816 |
+
.md\:grid-cols-\[minmax\(0\2c _45fr\)_minmax\(0\2c _15fr\)\] {
|
| 2817 |
+
grid-template-columns: minmax(0, 45fr) minmax(0, 15fr);
|
| 2818 |
+
}
|
| 2819 |
+
|
| 2820 |
+
.md\:text-2xl {
|
| 2821 |
+
font-size: 1.5rem;
|
| 2822 |
+
line-height: 2rem;
|
| 2823 |
+
}
|
| 2824 |
+
|
| 2825 |
+
.md\:text-7xl {
|
| 2826 |
+
font-size: 4.5rem;
|
| 2827 |
+
line-height: 1;
|
| 2828 |
+
}
|
| 2829 |
+
|
| 2830 |
+
.md\:text-6xl {
|
| 2831 |
+
font-size: 3.75rem;
|
| 2832 |
+
line-height: 1;
|
| 2833 |
+
}
|
| 2834 |
+
|
| 2835 |
+
.md\:text-xl {
|
| 2836 |
+
font-size: 1.25rem;
|
| 2837 |
+
line-height: 1.75rem;
|
| 2838 |
+
}
|
| 2839 |
+
|
| 2840 |
+
.md\:tracking-wide {
|
| 2841 |
+
letter-spacing: 0.025em;
|
| 2842 |
+
}
|
| 2843 |
+
|
| 2844 |
+
.md\:tracking-wider {
|
| 2845 |
+
letter-spacing: 0.05em;
|
| 2846 |
+
}
|
| 2847 |
+
}
|
| 2848 |
+
|
| 2849 |
+
@media (min-width: 1024px) {
|
| 2850 |
+
.lg\:space-x-6 > :not([hidden]) ~ :not([hidden]) {
|
| 2851 |
+
--tw-space-x-reverse: 0;
|
| 2852 |
+
margin-right: calc(1.5rem * var(--tw-space-x-reverse));
|
| 2853 |
+
margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse)));
|
| 2854 |
+
}
|
| 2855 |
+
}
|
| 2856 |
+
|
| 2857 |
+
@media (min-width: 1280px) {
|
| 2858 |
+
.xl\:grid-rows-\[1fr_2fr\] {
|
| 2859 |
+
grid-template-rows: 1fr 2fr;
|
| 2860 |
+
}
|
| 2861 |
+
}
|
| 2862 |
+
|
| 2863 |
+
.dark\:block:where(.dark, .dark *) {
|
| 2864 |
+
display: block;
|
| 2865 |
+
}
|
| 2866 |
+
|
| 2867 |
+
.dark\:flex:where(.dark, .dark *) {
|
| 2868 |
+
display: flex;
|
| 2869 |
+
}
|
| 2870 |
+
|
| 2871 |
+
.dark\:hidden:where(.dark, .dark *) {
|
| 2872 |
+
display: none;
|
| 2873 |
+
}
|
| 2874 |
+
|
| 2875 |
+
.dark\:border-destructive:where(.dark, .dark *) {
|
| 2876 |
+
border-color: hsl(var(--destructive));
|
| 2877 |
+
}
|
| 2878 |
+
|
| 2879 |
+
.dark\:bg-background:where(.dark, .dark *) {
|
| 2880 |
+
background-color: hsl(var(--background));
|
| 2881 |
+
}
|
| 2882 |
+
|
| 2883 |
+
.dark\:from-\[\#1c2024\]:where(.dark, .dark *) {
|
| 2884 |
+
--tw-gradient-from: #1c2024 var(--tw-gradient-from-position);
|
| 2885 |
+
--tw-gradient-to: rgb(28 32 36 / 0) var(--tw-gradient-to-position);
|
| 2886 |
+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
| 2887 |
+
}
|
| 2888 |
+
|
| 2889 |
+
.dark\:from-white:where(.dark, .dark *) {
|
| 2890 |
+
--tw-gradient-from: #fff var(--tw-gradient-from-position);
|
| 2891 |
+
--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
|
| 2892 |
+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
| 2893 |
+
}
|
| 2894 |
+
|
| 2895 |
+
.dark\:to-slate-300:where(.dark, .dark *) {
|
| 2896 |
+
--tw-gradient-to: #cbd5e1 var(--tw-gradient-to-position);
|
| 2897 |
+
}
|
| 2898 |
+
|
| 2899 |
+
.dark\:hover\:border-white:hover:where(.dark, .dark *) {
|
| 2900 |
+
--tw-border-opacity: 1;
|
| 2901 |
+
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
| 2902 |
+
}
|
| 2903 |
+
|
| 2904 |
+
.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]) {
|
| 2905 |
+
padding-right: 0px;
|
| 2906 |
+
}
|
| 2907 |
+
|
| 2908 |
+
.\[\&\>span\]\:line-clamp-1>span {
|
| 2909 |
+
overflow: hidden;
|
| 2910 |
+
display: -webkit-box;
|
| 2911 |
+
-webkit-box-orient: vertical;
|
| 2912 |
+
-webkit-line-clamp: 1;
|
| 2913 |
+
}
|
| 2914 |
+
|
| 2915 |
+
.\[\&\>span\]\:translate-x-0>span {
|
| 2916 |
+
--tw-translate-x: 0px;
|
| 2917 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 2918 |
+
}
|
| 2919 |
+
|
| 2920 |
+
.peer:checked ~ .peer-checked\:\[\&\>span\]\:flex>span {
|
| 2921 |
+
display: flex;
|
| 2922 |
+
}
|
| 2923 |
+
|
| 2924 |
+
.peer:checked ~ .peer-checked\:\[\&\>span\]\:translate-x-5>span {
|
| 2925 |
+
--tw-translate-x: 1.25rem;
|
| 2926 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 2927 |
+
}
|
| 2928 |
+
|
| 2929 |
+
.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div {
|
| 2930 |
+
--tw-translate-y: -3px;
|
| 2931 |
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
| 2932 |
+
}
|
| 2933 |
+
|
| 2934 |
+
.\[\&\>svg\]\:absolute>svg {
|
| 2935 |
+
position: absolute;
|
| 2936 |
+
}
|
| 2937 |
+
|
| 2938 |
+
.\[\&\>svg\]\:left-4>svg {
|
| 2939 |
+
left: 1rem;
|
| 2940 |
+
}
|
| 2941 |
+
|
| 2942 |
+
.\[\&\>svg\]\:top-4>svg {
|
| 2943 |
+
top: 1rem;
|
| 2944 |
+
}
|
| 2945 |
+
|
| 2946 |
+
.\[\&\>svg\]\:text-destructive>svg {
|
| 2947 |
+
color: hsl(var(--destructive));
|
| 2948 |
+
}
|
| 2949 |
+
|
| 2950 |
+
.\[\&\>svg\]\:text-foreground>svg {
|
| 2951 |
+
color: hsl(var(--foreground));
|
| 2952 |
+
}
|
| 2953 |
+
|
| 2954 |
+
.\[\&\>svg\~\*\]\:pl-7>svg~* {
|
| 2955 |
+
padding-left: 1.75rem;
|
| 2956 |
+
}
|
| 2957 |
+
|
| 2958 |
+
.\[\&\>tr\]\:last\:border-b-0:last-child>tr {
|
| 2959 |
+
border-bottom-width: 0px;
|
| 2960 |
+
}
|
| 2961 |
+
|
| 2962 |
+
.\[\&_p\]\:leading-relaxed p {
|
| 2963 |
+
line-height: 1.625;
|
| 2964 |
+
}
|
| 2965 |
+
|
| 2966 |
+
.\[\&_tr\:last-child\]\:border-0 tr:last-child {
|
| 2967 |
+
border-width: 0px;
|
| 2968 |
+
}
|
| 2969 |
+
|
| 2970 |
+
.\[\&_tr\]\:border-b tr {
|
| 2971 |
+
border-bottom-width: 1px;
|
| 2972 |
+
}
|
| 2973 |
+
|
src/requirements.txt
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file was autogenerated by uv via the following command:
|
| 2 |
+
# uv pip compile pyproject.toml -o src/requirements.txt
|
| 3 |
+
accelerate==0.34.2
|
| 4 |
+
# via peft
|
| 5 |
+
aiohappyeyeballs==2.4.3
|
| 6 |
+
# via aiohttp
|
| 7 |
+
aiohttp==3.12.14
|
| 8 |
+
# via
|
| 9 |
+
# datasets
|
| 10 |
+
# fsspec
|
| 11 |
+
# pyvespa
|
| 12 |
+
aiosignal==1.3.1
|
| 13 |
+
# via aiohttp
|
| 14 |
+
annotated-types==0.7.0
|
| 15 |
+
# via pydantic
|
| 16 |
+
anyio==4.6.0
|
| 17 |
+
# via
|
| 18 |
+
# httpx
|
| 19 |
+
# starlette
|
| 20 |
+
# watchfiles
|
| 21 |
+
async-timeout==4.0.3
|
| 22 |
+
# via aiohttp
|
| 23 |
+
attrs==24.2.0
|
| 24 |
+
# via aiohttp
|
| 25 |
+
beautifulsoup4==4.12.3
|
| 26 |
+
# via python-fasthtml
|
| 27 |
+
blis==0.7.11
|
| 28 |
+
# via thinc
|
| 29 |
+
cachetools==5.5.0
|
| 30 |
+
# via google-auth
|
| 31 |
+
catalogue==2.0.10
|
| 32 |
+
# via
|
| 33 |
+
# spacy
|
| 34 |
+
# srsly
|
| 35 |
+
# thinc
|
| 36 |
+
certifi==2024.8.30
|
| 37 |
+
# via
|
| 38 |
+
# httpcore
|
| 39 |
+
# httpx
|
| 40 |
+
# requests
|
| 41 |
+
cffi==1.17.1
|
| 42 |
+
# via cryptography
|
| 43 |
+
charset-normalizer==3.3.2
|
| 44 |
+
# via requests
|
| 45 |
+
click==8.1.7
|
| 46 |
+
# via
|
| 47 |
+
# typer
|
| 48 |
+
# uvicorn
|
| 49 |
+
cloudpathlib==0.20.0
|
| 50 |
+
# via weasel
|
| 51 |
+
colpali-engine==0.3.1
|
| 52 |
+
# via
|
| 53 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 54 |
+
# vidore-benchmark
|
| 55 |
+
confection==0.1.5
|
| 56 |
+
# via
|
| 57 |
+
# thinc
|
| 58 |
+
# weasel
|
| 59 |
+
contourpy==1.3.0
|
| 60 |
+
# via matplotlib
|
| 61 |
+
cryptography==44.0.1
|
| 62 |
+
# via pyvespa
|
| 63 |
+
cycler==0.12.1
|
| 64 |
+
# via matplotlib
|
| 65 |
+
cymem==2.0.8
|
| 66 |
+
# via
|
| 67 |
+
# preshed
|
| 68 |
+
# spacy
|
| 69 |
+
# thinc
|
| 70 |
+
datasets==2.21.0
|
| 71 |
+
# via
|
| 72 |
+
# mteb
|
| 73 |
+
# vidore-benchmark
|
| 74 |
+
dill==0.3.8
|
| 75 |
+
# via
|
| 76 |
+
# datasets
|
| 77 |
+
# multiprocess
|
| 78 |
+
docker==7.1.0
|
| 79 |
+
# via pyvespa
|
| 80 |
+
einops==0.8.0
|
| 81 |
+
# via
|
| 82 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 83 |
+
# vidore-benchmark
|
| 84 |
+
eval-type-backport==0.2.0
|
| 85 |
+
# via mteb
|
| 86 |
+
exceptiongroup==1.2.2
|
| 87 |
+
# via anyio
|
| 88 |
+
fastcore==1.7.11
|
| 89 |
+
# via
|
| 90 |
+
# fastlite
|
| 91 |
+
# python-fasthtml
|
| 92 |
+
# pyvespa
|
| 93 |
+
# sqlite-minutils
|
| 94 |
+
fastlite==0.0.11
|
| 95 |
+
# via python-fasthtml
|
| 96 |
+
filelock==3.16.1
|
| 97 |
+
# via
|
| 98 |
+
# datasets
|
| 99 |
+
# huggingface-hub
|
| 100 |
+
# torch
|
| 101 |
+
# transformers
|
| 102 |
+
fonttools==4.54.1
|
| 103 |
+
# via matplotlib
|
| 104 |
+
frozenlist==1.4.1
|
| 105 |
+
# via
|
| 106 |
+
# aiohttp
|
| 107 |
+
# aiosignal
|
| 108 |
+
fsspec==2024.6.1
|
| 109 |
+
# via
|
| 110 |
+
# datasets
|
| 111 |
+
# huggingface-hub
|
| 112 |
+
# torch
|
| 113 |
+
google-ai-generativelanguage==0.6.10
|
| 114 |
+
# via google-generativeai
|
| 115 |
+
google-api-core==2.21.0
|
| 116 |
+
# via
|
| 117 |
+
# google-ai-generativelanguage
|
| 118 |
+
# google-api-python-client
|
| 119 |
+
# google-generativeai
|
| 120 |
+
google-api-python-client==2.149.0
|
| 121 |
+
# via google-generativeai
|
| 122 |
+
google-auth==2.35.0
|
| 123 |
+
# via
|
| 124 |
+
# google-ai-generativelanguage
|
| 125 |
+
# google-api-core
|
| 126 |
+
# google-api-python-client
|
| 127 |
+
# google-auth-httplib2
|
| 128 |
+
# google-generativeai
|
| 129 |
+
google-auth-httplib2==0.2.0
|
| 130 |
+
# via google-api-python-client
|
| 131 |
+
google-generativeai==0.8.3
|
| 132 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 133 |
+
googleapis-common-protos==1.65.0
|
| 134 |
+
# via
|
| 135 |
+
# google-api-core
|
| 136 |
+
# grpcio-status
|
| 137 |
+
gputil==1.4.0
|
| 138 |
+
# via
|
| 139 |
+
# colpali-engine
|
| 140 |
+
# vidore-benchmark
|
| 141 |
+
grpcio==1.67.0
|
| 142 |
+
# via
|
| 143 |
+
# google-api-core
|
| 144 |
+
# grpcio-status
|
| 145 |
+
grpcio-status==1.67.0
|
| 146 |
+
# via google-api-core
|
| 147 |
+
h11==0.16.0
|
| 148 |
+
# via
|
| 149 |
+
# httpcore
|
| 150 |
+
# uvicorn
|
| 151 |
+
h2==4.1.0
|
| 152 |
+
# via httpx
|
| 153 |
+
hpack==4.0.0
|
| 154 |
+
# via h2
|
| 155 |
+
httpcore==1.0.6
|
| 156 |
+
# via httpx
|
| 157 |
+
httplib2==0.22.0
|
| 158 |
+
# via
|
| 159 |
+
# google-api-python-client
|
| 160 |
+
# google-auth-httplib2
|
| 161 |
+
httptools==0.6.1
|
| 162 |
+
# via uvicorn
|
| 163 |
+
httpx==0.27.2
|
| 164 |
+
# via
|
| 165 |
+
# python-fasthtml
|
| 166 |
+
# pyvespa
|
| 167 |
+
huggingface-hub==0.25.1
|
| 168 |
+
# via
|
| 169 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 170 |
+
# accelerate
|
| 171 |
+
# datasets
|
| 172 |
+
# peft
|
| 173 |
+
# sentence-transformers
|
| 174 |
+
# tokenizers
|
| 175 |
+
# transformers
|
| 176 |
+
hyperframe==6.0.1
|
| 177 |
+
# via h2
|
| 178 |
+
idna==3.10
|
| 179 |
+
# via
|
| 180 |
+
# anyio
|
| 181 |
+
# httpx
|
| 182 |
+
# requests
|
| 183 |
+
# yarl
|
| 184 |
+
itsdangerous==2.2.0
|
| 185 |
+
# via python-fasthtml
|
| 186 |
+
jinja2==3.1.6
|
| 187 |
+
# via
|
| 188 |
+
# pyvespa
|
| 189 |
+
# spacy
|
| 190 |
+
# torch
|
| 191 |
+
joblib==1.4.2
|
| 192 |
+
# via scikit-learn
|
| 193 |
+
kiwisolver==1.4.7
|
| 194 |
+
# via matplotlib
|
| 195 |
+
langcodes==3.4.1
|
| 196 |
+
# via spacy
|
| 197 |
+
language-data==1.2.0
|
| 198 |
+
# via langcodes
|
| 199 |
+
loguru==0.7.2
|
| 200 |
+
# via vidore-benchmark
|
| 201 |
+
lucide-fasthtml==0.0.9
|
| 202 |
+
# via shad4fast
|
| 203 |
+
lxml==5.3.0
|
| 204 |
+
# via
|
| 205 |
+
# lucide-fasthtml
|
| 206 |
+
# pyvespa
|
| 207 |
+
marisa-trie==1.2.1
|
| 208 |
+
# via language-data
|
| 209 |
+
markdown-it-py==3.0.0
|
| 210 |
+
# via rich
|
| 211 |
+
markupsafe==2.1.5
|
| 212 |
+
# via jinja2
|
| 213 |
+
matplotlib==3.9.2
|
| 214 |
+
# via
|
| 215 |
+
# seaborn
|
| 216 |
+
# vidore-benchmark
|
| 217 |
+
mdurl==0.1.2
|
| 218 |
+
# via markdown-it-py
|
| 219 |
+
mpmath==1.3.0
|
| 220 |
+
# via sympy
|
| 221 |
+
mteb==1.15.3
|
| 222 |
+
# via vidore-benchmark
|
| 223 |
+
multidict==6.1.0
|
| 224 |
+
# via
|
| 225 |
+
# aiohttp
|
| 226 |
+
# yarl
|
| 227 |
+
multiprocess==0.70.16
|
| 228 |
+
# via datasets
|
| 229 |
+
murmurhash==1.0.10
|
| 230 |
+
# via
|
| 231 |
+
# preshed
|
| 232 |
+
# spacy
|
| 233 |
+
# thinc
|
| 234 |
+
networkx==3.3
|
| 235 |
+
# via torch
|
| 236 |
+
numpy==1.26.4
|
| 237 |
+
# via
|
| 238 |
+
# accelerate
|
| 239 |
+
# blis
|
| 240 |
+
# colpali-engine
|
| 241 |
+
# contourpy
|
| 242 |
+
# datasets
|
| 243 |
+
# matplotlib
|
| 244 |
+
# mteb
|
| 245 |
+
# pandas
|
| 246 |
+
# peft
|
| 247 |
+
# pyarrow
|
| 248 |
+
# scikit-learn
|
| 249 |
+
# scipy
|
| 250 |
+
# seaborn
|
| 251 |
+
# spacy
|
| 252 |
+
# thinc
|
| 253 |
+
# transformers
|
| 254 |
+
# vidore-benchmark
|
| 255 |
+
oauthlib==3.2.2
|
| 256 |
+
# via python-fasthtml
|
| 257 |
+
packaging==24.1
|
| 258 |
+
# via
|
| 259 |
+
# accelerate
|
| 260 |
+
# datasets
|
| 261 |
+
# fastcore
|
| 262 |
+
# huggingface-hub
|
| 263 |
+
# matplotlib
|
| 264 |
+
# peft
|
| 265 |
+
# spacy
|
| 266 |
+
# thinc
|
| 267 |
+
# transformers
|
| 268 |
+
# weasel
|
| 269 |
+
pandas==2.2.3
|
| 270 |
+
# via
|
| 271 |
+
# datasets
|
| 272 |
+
# seaborn
|
| 273 |
+
pdf2image==1.17.0
|
| 274 |
+
# via vidore-benchmark
|
| 275 |
+
peft==0.11.1
|
| 276 |
+
# via
|
| 277 |
+
# colpali-engine
|
| 278 |
+
# vidore-benchmark
|
| 279 |
+
pillow==10.4.0
|
| 280 |
+
# via
|
| 281 |
+
# colpali-engine
|
| 282 |
+
# matplotlib
|
| 283 |
+
# pdf2image
|
| 284 |
+
# sentence-transformers
|
| 285 |
+
# vidore-benchmark
|
| 286 |
+
pip==24.3.1
|
| 287 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 288 |
+
polars==1.9.0
|
| 289 |
+
# via mteb
|
| 290 |
+
preshed==3.0.9
|
| 291 |
+
# via
|
| 292 |
+
# spacy
|
| 293 |
+
# thinc
|
| 294 |
+
proto-plus==1.24.0
|
| 295 |
+
# via
|
| 296 |
+
# google-ai-generativelanguage
|
| 297 |
+
# google-api-core
|
| 298 |
+
protobuf==5.29.5
|
| 299 |
+
# via
|
| 300 |
+
# google-ai-generativelanguage
|
| 301 |
+
# google-api-core
|
| 302 |
+
# google-generativeai
|
| 303 |
+
# googleapis-common-protos
|
| 304 |
+
# grpcio-status
|
| 305 |
+
# proto-plus
|
| 306 |
+
psutil==6.0.0
|
| 307 |
+
# via
|
| 308 |
+
# accelerate
|
| 309 |
+
# peft
|
| 310 |
+
pyarrow==17.0.0
|
| 311 |
+
# via datasets
|
| 312 |
+
pyasn1==0.6.1
|
| 313 |
+
# via
|
| 314 |
+
# pyasn1-modules
|
| 315 |
+
# rsa
|
| 316 |
+
pyasn1-modules==0.4.1
|
| 317 |
+
# via google-auth
|
| 318 |
+
pycparser==2.22
|
| 319 |
+
# via cffi
|
| 320 |
+
pydantic==2.9.2
|
| 321 |
+
# via
|
| 322 |
+
# confection
|
| 323 |
+
# google-generativeai
|
| 324 |
+
# mteb
|
| 325 |
+
# spacy
|
| 326 |
+
# thinc
|
| 327 |
+
# weasel
|
| 328 |
+
pydantic-core==2.23.4
|
| 329 |
+
# via pydantic
|
| 330 |
+
pygments==2.18.0
|
| 331 |
+
# via rich
|
| 332 |
+
pyparsing==3.1.4
|
| 333 |
+
# via
|
| 334 |
+
# httplib2
|
| 335 |
+
# matplotlib
|
| 336 |
+
pypdf==5.0.1
|
| 337 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 338 |
+
python-dateutil==2.9.0.post0
|
| 339 |
+
# via
|
| 340 |
+
# matplotlib
|
| 341 |
+
# pandas
|
| 342 |
+
# python-fasthtml
|
| 343 |
+
# pyvespa
|
| 344 |
+
python-dotenv==1.0.1
|
| 345 |
+
# via
|
| 346 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 347 |
+
# uvicorn
|
| 348 |
+
# vidore-benchmark
|
| 349 |
+
python-fasthtml==0.6.9
|
| 350 |
+
# via
|
| 351 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 352 |
+
# lucide-fasthtml
|
| 353 |
+
# shad4fast
|
| 354 |
+
python-multipart==0.0.18
|
| 355 |
+
# via python-fasthtml
|
| 356 |
+
pytrec-eval-terrier==0.5.6
|
| 357 |
+
# via mteb
|
| 358 |
+
pytz==2024.2
|
| 359 |
+
# via pandas
|
| 360 |
+
pyvespa==0.50.0
|
| 361 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 362 |
+
pyyaml==6.0.2
|
| 363 |
+
# via
|
| 364 |
+
# accelerate
|
| 365 |
+
# datasets
|
| 366 |
+
# huggingface-hub
|
| 367 |
+
# peft
|
| 368 |
+
# transformers
|
| 369 |
+
# uvicorn
|
| 370 |
+
regex==2024.9.11
|
| 371 |
+
# via transformers
|
| 372 |
+
requests==2.32.4
|
| 373 |
+
# via
|
| 374 |
+
# colpali-engine
|
| 375 |
+
# datasets
|
| 376 |
+
# docker
|
| 377 |
+
# google-api-core
|
| 378 |
+
# huggingface-hub
|
| 379 |
+
# lucide-fasthtml
|
| 380 |
+
# mteb
|
| 381 |
+
# pyvespa
|
| 382 |
+
# requests-toolbelt
|
| 383 |
+
# spacy
|
| 384 |
+
# transformers
|
| 385 |
+
# weasel
|
| 386 |
+
requests-toolbelt==1.0.0
|
| 387 |
+
# via pyvespa
|
| 388 |
+
rich==13.9.2
|
| 389 |
+
# via
|
| 390 |
+
# mteb
|
| 391 |
+
# typer
|
| 392 |
+
rsa==4.9
|
| 393 |
+
# via google-auth
|
| 394 |
+
safetensors==0.4.5
|
| 395 |
+
# via
|
| 396 |
+
# accelerate
|
| 397 |
+
# peft
|
| 398 |
+
# transformers
|
| 399 |
+
scikit-learn==1.5.2
|
| 400 |
+
# via
|
| 401 |
+
# mteb
|
| 402 |
+
# sentence-transformers
|
| 403 |
+
scipy==1.14.1
|
| 404 |
+
# via
|
| 405 |
+
# mteb
|
| 406 |
+
# scikit-learn
|
| 407 |
+
# sentence-transformers
|
| 408 |
+
seaborn==0.13.2
|
| 409 |
+
# via vidore-benchmark
|
| 410 |
+
sentence-transformers==3.1.1
|
| 411 |
+
# via
|
| 412 |
+
# mteb
|
| 413 |
+
# vidore-benchmark
|
| 414 |
+
sentencepiece==0.2.0
|
| 415 |
+
# via vidore-benchmark
|
| 416 |
+
setuptools==78.1.1
|
| 417 |
+
# via
|
| 418 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 419 |
+
# marisa-trie
|
| 420 |
+
# spacy
|
| 421 |
+
# thinc
|
| 422 |
+
shad4fast==1.2.1
|
| 423 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 424 |
+
shellingham==1.5.4
|
| 425 |
+
# via typer
|
| 426 |
+
six==1.16.0
|
| 427 |
+
# via python-dateutil
|
| 428 |
+
smart-open==7.0.5
|
| 429 |
+
# via weasel
|
| 430 |
+
sniffio==1.3.1
|
| 431 |
+
# via
|
| 432 |
+
# anyio
|
| 433 |
+
# httpx
|
| 434 |
+
soupsieve==2.6
|
| 435 |
+
# via beautifulsoup4
|
| 436 |
+
spacy==3.7.5
|
| 437 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 438 |
+
spacy-legacy==3.0.12
|
| 439 |
+
# via spacy
|
| 440 |
+
spacy-loggers==1.0.5
|
| 441 |
+
# via spacy
|
| 442 |
+
sqlite-minutils==3.37.0.post3
|
| 443 |
+
# via fastlite
|
| 444 |
+
srsly==2.4.8
|
| 445 |
+
# via
|
| 446 |
+
# confection
|
| 447 |
+
# spacy
|
| 448 |
+
# thinc
|
| 449 |
+
# weasel
|
| 450 |
+
starlette==0.47.2
|
| 451 |
+
# via python-fasthtml
|
| 452 |
+
sympy==1.13.3
|
| 453 |
+
# via torch
|
| 454 |
+
tenacity==9.0.0
|
| 455 |
+
# via pyvespa
|
| 456 |
+
thinc==8.2.5
|
| 457 |
+
# via spacy
|
| 458 |
+
threadpoolctl==3.5.0
|
| 459 |
+
# via scikit-learn
|
| 460 |
+
tokenizers==0.20.0
|
| 461 |
+
# via transformers
|
| 462 |
+
torch==2.7.1
|
| 463 |
+
# via
|
| 464 |
+
# visual-retrieval-colpali (pyproject.toml)
|
| 465 |
+
# accelerate
|
| 466 |
+
# colpali-engine
|
| 467 |
+
# mteb
|
| 468 |
+
# peft
|
| 469 |
+
# sentence-transformers
|
| 470 |
+
# vidore-benchmark
|
| 471 |
+
tqdm==4.66.5
|
| 472 |
+
# via
|
| 473 |
+
# datasets
|
| 474 |
+
# google-generativeai
|
| 475 |
+
# huggingface-hub
|
| 476 |
+
# mteb
|
| 477 |
+
# peft
|
| 478 |
+
# sentence-transformers
|
| 479 |
+
# spacy
|
| 480 |
+
# transformers
|
| 481 |
+
transformers==4.53.0
|
| 482 |
+
# via
|
| 483 |
+
# colpali-engine
|
| 484 |
+
# peft
|
| 485 |
+
# sentence-transformers
|
| 486 |
+
# vidore-benchmark
|
| 487 |
+
typer==0.12.5
|
| 488 |
+
# via
|
| 489 |
+
# spacy
|
| 490 |
+
# vidore-benchmark
|
| 491 |
+
# weasel
|
| 492 |
+
typing-extensions==4.12.2
|
| 493 |
+
# via
|
| 494 |
+
# anyio
|
| 495 |
+
# cloudpathlib
|
| 496 |
+
# google-generativeai
|
| 497 |
+
# huggingface-hub
|
| 498 |
+
# mteb
|
| 499 |
+
# multidict
|
| 500 |
+
# pydantic
|
| 501 |
+
# pydantic-core
|
| 502 |
+
# pypdf
|
| 503 |
+
# pyvespa
|
| 504 |
+
# rich
|
| 505 |
+
# torch
|
| 506 |
+
# typer
|
| 507 |
+
# uvicorn
|
| 508 |
+
tzdata==2024.2
|
| 509 |
+
# via pandas
|
| 510 |
+
uritemplate==4.1.1
|
| 511 |
+
# via google-api-python-client
|
| 512 |
+
urllib3==2.5.0
|
| 513 |
+
# via
|
| 514 |
+
# docker
|
| 515 |
+
# requests
|
| 516 |
+
uvicorn==0.31.0
|
| 517 |
+
# via python-fasthtml
|
| 518 |
+
uvloop==0.20.0
|
| 519 |
+
# via uvicorn
|
| 520 |
+
vespacli==8.391.23
|
| 521 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 522 |
+
vidore-benchmark==4.0.0
|
| 523 |
+
# via visual-retrieval-colpali (pyproject.toml)
|
| 524 |
+
wasabi==1.1.3
|
| 525 |
+
# via
|
| 526 |
+
# spacy
|
| 527 |
+
# thinc
|
| 528 |
+
# weasel
|
| 529 |
+
watchfiles==0.24.0
|
| 530 |
+
# via uvicorn
|
| 531 |
+
weasel==0.4.1
|
| 532 |
+
# via spacy
|
| 533 |
+
websockets==13.1
|
| 534 |
+
# via uvicorn
|
| 535 |
+
wrapt==1.16.0
|
| 536 |
+
# via smart-open
|
| 537 |
+
xxhash==3.5.0
|
| 538 |
+
# via datasets
|
| 539 |
+
yarl==1.13.1
|
| 540 |
+
# via aiohttp
|
src/static/img/colpali_child.png
ADDED
|
Git LFS Details
|
src/static/img/linkedin.svg
ADDED
|
|
src/static/img/vespa-colpali.png
ADDED
|
Git LFS Details
|
src/static/img/visual-retrieval-demoapp-arch.png
ADDED
|
Git LFS Details
|
src/static/img/x.svg
ADDED
|
|
src/static/js/highlightjs-theme.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(function () {
|
| 2 |
+
function getPreferredTheme() {
|
| 3 |
+
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
| 4 |
+
return 'dark';
|
| 5 |
+
}
|
| 6 |
+
return 'light';
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
function syncHighlightTheme() {
|
| 10 |
+
const link = document.getElementById('highlight-theme');
|
| 11 |
+
const preferredTheme = getPreferredTheme();
|
| 12 |
+
link.href = preferredTheme === 'dark' ?
|
| 13 |
+
'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/github-dark.min.css' :
|
| 14 |
+
'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/github.min.css';
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
// Apply the correct theme immediately
|
| 18 |
+
syncHighlightTheme();
|
| 19 |
+
|
| 20 |
+
// Observe changes in the 'dark' class on the <html> element
|
| 21 |
+
const observer = new MutationObserver(syncHighlightTheme);
|
| 22 |
+
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['class']});
|
| 23 |
+
})();
|
src/tailwind.config.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function filterDefault(values) {
|
| 2 |
+
return Object.fromEntries(
|
| 3 |
+
Object.entries(values).filter(([key]) => key !== "DEFAULT"),
|
| 4 |
+
);
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
/** @type {import('tailwindcss').Config} */
|
| 8 |
+
export default {
|
| 9 |
+
darkMode: ["selector"],
|
| 10 |
+
content: [
|
| 11 |
+
"../**/*.py",
|
| 12 |
+
"../.venv/lib/python3.12/site-packages/shad4fast/**/*.{py,js}",
|
| 13 |
+
],
|
| 14 |
+
theme: {
|
| 15 |
+
container: {
|
| 16 |
+
center: true,
|
| 17 |
+
padding: "2rem",
|
| 18 |
+
screens: {
|
| 19 |
+
"2xl": "1400px",
|
| 20 |
+
},
|
| 21 |
+
},
|
| 22 |
+
extend: {
|
| 23 |
+
animation: {
|
| 24 |
+
"accordion-down": "accordion-down 0.2s ease-out",
|
| 25 |
+
"accordion-up": "accordion-up 0.2s ease-out",
|
| 26 |
+
},
|
| 27 |
+
animationDelay: ({theme}) => ({
|
| 28 |
+
...theme("transitionDelay"),
|
| 29 |
+
}),
|
| 30 |
+
animationDuration: ({theme}) => ({
|
| 31 |
+
0: "0ms",
|
| 32 |
+
...theme("transitionDuration"),
|
| 33 |
+
}),
|
| 34 |
+
animationTimingFunction: ({theme}) => ({
|
| 35 |
+
...theme("transitionTimingFunction"),
|
| 36 |
+
}),
|
| 37 |
+
animationFillMode: {
|
| 38 |
+
none: "none",
|
| 39 |
+
forwards: "forwards",
|
| 40 |
+
backwards: "backwards",
|
| 41 |
+
both: "both",
|
| 42 |
+
},
|
| 43 |
+
animationDirection: {
|
| 44 |
+
normal: "normal",
|
| 45 |
+
reverse: "reverse",
|
| 46 |
+
alternate: "alternate",
|
| 47 |
+
"alternate-reverse": "alternate-reverse",
|
| 48 |
+
},
|
| 49 |
+
animationOpacity: ({theme}) => ({
|
| 50 |
+
DEFAULT: 0,
|
| 51 |
+
...theme("opacity"),
|
| 52 |
+
}),
|
| 53 |
+
animationTranslate: ({theme}) => ({
|
| 54 |
+
DEFAULT: "100%",
|
| 55 |
+
...theme("translate"),
|
| 56 |
+
}),
|
| 57 |
+
animationScale: ({theme}) => ({
|
| 58 |
+
DEFAULT: 0,
|
| 59 |
+
...theme("scale"),
|
| 60 |
+
}),
|
| 61 |
+
animationRotate: ({theme}) => ({
|
| 62 |
+
DEFAULT: "30deg",
|
| 63 |
+
...theme("rotate"),
|
| 64 |
+
}),
|
| 65 |
+
animationRepeat: {
|
| 66 |
+
0: "0",
|
| 67 |
+
1: "1",
|
| 68 |
+
infinite: "infinite",
|
| 69 |
+
},
|
| 70 |
+
keyframes: {
|
| 71 |
+
enter: {
|
| 72 |
+
from: {
|
| 73 |
+
opacity: "var(--tw-enter-opacity, 1)",
|
| 74 |
+
transform:
|
| 75 |
+
"translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))",
|
| 76 |
+
},
|
| 77 |
+
},
|
| 78 |
+
exit: {
|
| 79 |
+
to: {
|
| 80 |
+
opacity: "var(--tw-exit-opacity, 1)",
|
| 81 |
+
transform:
|
| 82 |
+
"translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))",
|
| 83 |
+
},
|
| 84 |
+
},
|
| 85 |
+
},
|
| 86 |
+
colors: {
|
| 87 |
+
border: "hsl(var(--border))",
|
| 88 |
+
input: "hsl(var(--input))",
|
| 89 |
+
ring: "hsl(var(--ring))",
|
| 90 |
+
background: "hsl(var(--background))",
|
| 91 |
+
foreground: "hsl(var(--foreground))",
|
| 92 |
+
primary: {
|
| 93 |
+
DEFAULT: "hsl(var(--primary))",
|
| 94 |
+
foreground: "hsl(var(--primary-foreground))",
|
| 95 |
+
},
|
| 96 |
+
secondary: {
|
| 97 |
+
DEFAULT: "hsl(var(--secondary))",
|
| 98 |
+
foreground: "hsl(var(--secondary-foreground))",
|
| 99 |
+
},
|
| 100 |
+
destructive: {
|
| 101 |
+
DEFAULT: "hsl(var(--destructive))",
|
| 102 |
+
foreground: "hsl(var(--destructive-foreground))",
|
| 103 |
+
},
|
| 104 |
+
muted: {
|
| 105 |
+
DEFAULT: "hsl(var(--muted))",
|
| 106 |
+
foreground: "hsl(var(--muted-foreground))",
|
| 107 |
+
},
|
| 108 |
+
accent: {
|
| 109 |
+
DEFAULT: "hsl(var(--accent))",
|
| 110 |
+
foreground: "hsl(var(--accent-foreground))",
|
| 111 |
+
},
|
| 112 |
+
popover: {
|
| 113 |
+
DEFAULT: "hsl(var(--popover))",
|
| 114 |
+
foreground: "hsl(var(--popover-foreground))",
|
| 115 |
+
},
|
| 116 |
+
card: {
|
| 117 |
+
DEFAULT: "hsl(var(--card))",
|
| 118 |
+
foreground: "hsl(var(--card-foreground))",
|
| 119 |
+
},
|
| 120 |
+
},
|
| 121 |
+
borderRadius: {
|
| 122 |
+
lg: `var(--radius)`,
|
| 123 |
+
md: `calc(var(--radius) - 2px)`,
|
| 124 |
+
sm: "calc(var(--radius) - 4px)",
|
| 125 |
+
},
|
| 126 |
+
},
|
| 127 |
+
},
|
| 128 |
+
plugins: [
|
| 129 |
+
function ({addUtilities, matchUtilities, theme}) {
|
| 130 |
+
addUtilities({
|
| 131 |
+
"@keyframes enter": theme("keyframes.enter"),
|
| 132 |
+
"@keyframes exit": theme("keyframes.exit"),
|
| 133 |
+
".animate-in": {
|
| 134 |
+
animationName: "enter",
|
| 135 |
+
animationDuration: theme("animationDuration.DEFAULT"),
|
| 136 |
+
"--tw-enter-opacity": "initial",
|
| 137 |
+
"--tw-enter-scale": "initial",
|
| 138 |
+
"--tw-enter-rotate": "initial",
|
| 139 |
+
"--tw-enter-translate-x": "initial",
|
| 140 |
+
"--tw-enter-translate-y": "initial",
|
| 141 |
+
},
|
| 142 |
+
".animate-out": {
|
| 143 |
+
animationName: "exit",
|
| 144 |
+
animationDuration: theme("animationDuration.DEFAULT"),
|
| 145 |
+
"--tw-exit-opacity": "initial",
|
| 146 |
+
"--tw-exit-scale": "initial",
|
| 147 |
+
"--tw-exit-rotate": "initial",
|
| 148 |
+
"--tw-exit-translate-x": "initial",
|
| 149 |
+
"--tw-exit-translate-y": "initial",
|
| 150 |
+
},
|
| 151 |
+
});
|
| 152 |
+
|
| 153 |
+
matchUtilities(
|
| 154 |
+
{
|
| 155 |
+
"fade-in": (value) => ({"--tw-enter-opacity": value}),
|
| 156 |
+
"fade-out": (value) => ({"--tw-exit-opacity": value}),
|
| 157 |
+
},
|
| 158 |
+
{values: theme("animationOpacity")},
|
| 159 |
+
);
|
| 160 |
+
|
| 161 |
+
matchUtilities(
|
| 162 |
+
{
|
| 163 |
+
"zoom-in": (value) => ({"--tw-enter-scale": value}),
|
| 164 |
+
"zoom-out": (value) => ({"--tw-exit-scale": value}),
|
| 165 |
+
},
|
| 166 |
+
{values: theme("animationScale")},
|
| 167 |
+
);
|
| 168 |
+
|
| 169 |
+
matchUtilities(
|
| 170 |
+
{
|
| 171 |
+
"spin-in": (value) => ({"--tw-enter-rotate": value}),
|
| 172 |
+
"spin-out": (value) => ({"--tw-exit-rotate": value}),
|
| 173 |
+
},
|
| 174 |
+
{values: theme("animationRotate")},
|
| 175 |
+
);
|
| 176 |
+
|
| 177 |
+
matchUtilities(
|
| 178 |
+
{
|
| 179 |
+
"slide-in-from-top": (value) => ({
|
| 180 |
+
"--tw-enter-translate-y": `-${value}`,
|
| 181 |
+
}),
|
| 182 |
+
"slide-in-from-bottom": (value) => ({
|
| 183 |
+
"--tw-enter-translate-y": value,
|
| 184 |
+
}),
|
| 185 |
+
"slide-in-from-left": (value) => ({
|
| 186 |
+
"--tw-enter-translate-x": `-${value}`,
|
| 187 |
+
}),
|
| 188 |
+
"slide-in-from-right": (value) => ({
|
| 189 |
+
"--tw-enter-translate-x": value,
|
| 190 |
+
}),
|
| 191 |
+
"slide-out-to-top": (value) => ({
|
| 192 |
+
"--tw-exit-translate-y": `-${value}`,
|
| 193 |
+
}),
|
| 194 |
+
"slide-out-to-bottom": (value) => ({
|
| 195 |
+
"--tw-exit-translate-y": value,
|
| 196 |
+
}),
|
| 197 |
+
"slide-out-to-left": (value) => ({
|
| 198 |
+
"--tw-exit-translate-x": `-${value}`,
|
| 199 |
+
}),
|
| 200 |
+
"slide-out-to-right": (value) => ({
|
| 201 |
+
"--tw-exit-translate-x": value,
|
| 202 |
+
}),
|
| 203 |
+
},
|
| 204 |
+
{values: theme("animationTranslate")},
|
| 205 |
+
);
|
| 206 |
+
|
| 207 |
+
matchUtilities(
|
| 208 |
+
{duration: (value) => ({animationDuration: value})},
|
| 209 |
+
{values: filterDefault(theme("animationDuration"))},
|
| 210 |
+
);
|
| 211 |
+
|
| 212 |
+
matchUtilities(
|
| 213 |
+
{delay: (value) => ({animationDelay: value})},
|
| 214 |
+
{values: theme("animationDelay")},
|
| 215 |
+
);
|
| 216 |
+
|
| 217 |
+
matchUtilities(
|
| 218 |
+
{ease: (value) => ({animationTimingFunction: value})},
|
| 219 |
+
{values: filterDefault(theme("animationTimingFunction"))},
|
| 220 |
+
);
|
| 221 |
+
|
| 222 |
+
addUtilities({
|
| 223 |
+
".running": {animationPlayState: "running"},
|
| 224 |
+
".paused": {animationPlayState: "paused"},
|
| 225 |
+
});
|
| 226 |
+
|
| 227 |
+
matchUtilities(
|
| 228 |
+
{"fill-mode": (value) => ({animationFillMode: value})},
|
| 229 |
+
{values: theme("animationFillMode")},
|
| 230 |
+
);
|
| 231 |
+
|
| 232 |
+
matchUtilities(
|
| 233 |
+
{direction: (value) => ({animationDirection: value})},
|
| 234 |
+
{values: theme("animationDirection")},
|
| 235 |
+
);
|
| 236 |
+
|
| 237 |
+
matchUtilities(
|
| 238 |
+
{repeat: (value) => ({animationIterationCount: value})},
|
| 239 |
+
{values: theme("animationRepeat")},
|
| 240 |
+
);
|
| 241 |
+
},
|
| 242 |
+
],
|
| 243 |
+
};
|
src/tailwindcss
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:327703a4646081906e11d116ff4e8e43076466c3d269282bbe612555b9fe0c58
|
| 3 |
+
size 47351504
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
vespa_feed_to_hf_dataset.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
import os
|
| 4 |
+
import base64
|
| 5 |
+
from PIL import Image
|
| 6 |
+
import io
|
| 7 |
+
from datasets import Dataset, Image as HFImage
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from tqdm import tqdm
|
| 10 |
+
|
| 11 |
+
load_dotenv()
|
| 12 |
+
|
| 13 |
+
df = pd.read_json("output/vespa_feed_full.jsonl", lines=True)
|
| 14 |
+
df = pd.json_normalize(df["fields"].tolist())
|
| 15 |
+
|
| 16 |
+
dataset_dir = Path("hf_dataset")
|
| 17 |
+
image_dir = dataset_dir / "images"
|
| 18 |
+
os.makedirs(image_dir, exist_ok=True)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def save_image(image_data, filename):
|
| 22 |
+
img_data = base64.b64decode(image_data)
|
| 23 |
+
img = Image.open(io.BytesIO(img_data))
|
| 24 |
+
img.save(filename)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
for idx, row in tqdm(df.iterrows()):
|
| 28 |
+
blur_filename = os.path.join(image_dir, f"blur_{idx}.jpg")
|
| 29 |
+
full_filename = os.path.join(image_dir, f"full_{idx}.jpg")
|
| 30 |
+
save_image(row["blur_image"], blur_filename)
|
| 31 |
+
save_image(row["full_image"], full_filename)
|
| 32 |
+
df.at[idx, "blur_image"] = blur_filename
|
| 33 |
+
df.at[idx, "full_image"] = full_filename
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
# Step 3: Convert to Hugging Face Dataset
|
| 37 |
+
dataset = (
|
| 38 |
+
Dataset.from_dict(df.to_dict(orient="list"))
|
| 39 |
+
.cast_column("blur_image", HFImage())
|
| 40 |
+
.cast_column("full_image", HFImage())
|
| 41 |
+
)
|
| 42 |
+
dataset.push_to_hub("vespa-engine/gpfg-QA", private=True)
|