├── .github └── workflows │ ├── publish.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── llm_nomic_api_embed.py ├── pyproject.toml └── tests ├── cassettes └── test_nomic_api_embed │ ├── test_embed.yaml │ ├── test_embed_combination.yaml │ └── test_embed_vision.yaml ├── conftest.py └── test_nomic_api_embed.py /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v5 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | cache: pip 23 | cache-dependency-path: pyproject.toml 24 | - name: Install dependencies 25 | run: | 26 | pip install -e '.[test]' 27 | - name: Run tests 28 | run: | 29 | pytest 30 | deploy: 31 | runs-on: ubuntu-latest 32 | needs: [test] 33 | environment: release 34 | permissions: 35 | id-token: write 36 | steps: 37 | - uses: actions/checkout@v4 38 | - name: Set up Python 39 | uses: actions/setup-python@v5 40 | with: 41 | python-version: "3.13" 42 | cache: pip 43 | cache-dependency-path: pyproject.toml 44 | - name: Install dependencies 45 | run: | 46 | pip install setuptools wheel build 47 | - name: Build 48 | run: | 49 | python -m build 50 | - name: Publish 51 | uses: pypa/gh-action-pypi-publish@release/v1 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | test: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Set up Python ${{ matrix.python-version }} 17 | uses: actions/setup-python@v5 18 | with: 19 | python-version: ${{ matrix.python-version }} 20 | cache: pip 21 | cache-dependency-path: pyproject.toml 22 | - name: Install dependencies 23 | run: | 24 | pip install -e '.[test]' 25 | - name: Run tests 26 | run: | 27 | pytest 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | venv 6 | .eggs 7 | .pytest_cache 8 | *.egg-info 9 | .DS_Store 10 | .vscode 11 | dist 12 | build 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # llm-nomic-api-embed 2 | 3 | [![PyPI](https://img.shields.io/pypi/v/llm-nomic-api-embed.svg)](https://pypi.org/project/llm-nomic-api-embed/) 4 | [![Changelog](https://img.shields.io/github/v/release/simonw/llm-nomic-api-embed?include_prereleases&label=changelog)](https://github.com/simonw/llm-nomic-api-embed/releases) 5 | [![Tests](https://github.com/simonw/llm-nomic-api-embed/actions/workflows/test.yml/badge.svg)](https://github.com/simonw/llm-nomic-api-embed/actions/workflows/test.yml) 6 | [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/llm-nomic-api-embed/blob/main/LICENSE) 7 | 8 | Create embeddings using the Nomic API 9 | 10 | ## Installation 11 | 12 | Install this plugin in the same environment as [LLM](https://llm.datasette.io/). 13 | ```bash 14 | llm install llm-nomic-api-embed 15 | ``` 16 | ## Usage 17 | 18 | This plugin requires [a Nomic API key](https://atlas.nomic.ai/). These include a generous free allowance for their embedding API. 19 | 20 | Configure the key like this: 21 | ```bash 22 | llm keys set nomic 23 | # Paste key here 24 | ``` 25 | You can then use the Nomic embedding models like this: 26 | ```bash 27 | llm embed -m nomic-1.5 -c 'hello world' 28 | ``` 29 | This will return a 768 item floating point array as JSON. 30 | 31 | See [the LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/index.html) for more you can do with the tool. 32 | 33 | ## Models 34 | 35 | Run `llm embed-models` for a full list. The Nomic models are: 36 | 37 | ``` 38 | nomic-embed-text-v1 (aliases: nomic-1) 39 | nomic-embed-text-v1.5 (aliases: nomic-1.5) 40 | nomic-embed-text-v1.5-512 (aliases: nomic-1.5-512) 41 | nomic-embed-text-v1.5-256 (aliases: nomic-1.5-256) 42 | nomic-embed-text-v1.5-128 (aliases: nomic-1.5-128) 43 | nomic-embed-text-v1.5-64 (aliases: nomic-1.5-64) 44 | nomic-embed-vision-v1 45 | nomic-embed-vision-v1.5 46 | nomic-embed-combined-v1 47 | nomic-embed-combined-v1.5 48 | ``` 49 | Vision models can be used with image files using the `--binary` option, for example: 50 | 51 | ```bash 52 | llm embed-multi images --files . '*.png' \ 53 | --binary --model nomic-embed-vision-v1.5 54 | ``` 55 | 56 | ### Combined vision and text models 57 | 58 | The `nomic-embed-combined-v1` and `nomic-embed-combined-v1.5` models are special - they will automatically use their respective text models for text inputs and their respective vision models for images. 59 | 60 | This means you can use them to create a collection that mixes images and text, or you can create an image collection with them and then use text to find similar images. 61 | 62 | Here's how do do that for a `photos/` directory full of JPEGs: 63 | 64 | ```bash 65 | llm embed-multi --binary -m nomic-embed-combined-v1.5 \ 66 | -d photos.db photos --files photos/ '*.jpeg' 67 | ``` 68 | Then run similarity searches like this: 69 | ```bash 70 | llm similar photos -d photos.db -c pelican 71 | ``` 72 | 73 | ## Development 74 | 75 | To set up this plugin locally, first checkout the code. Then create a new virtual environment: 76 | ```bash 77 | cd llm-nomic-api-embed 78 | python3 -m venv venv 79 | source venv/bin/activate 80 | ``` 81 | Now install the dependencies and test dependencies: 82 | ```bash 83 | llm install -e '.[test]' 84 | ``` 85 | To run the tests: 86 | ```bash 87 | pytest 88 | ``` 89 | -------------------------------------------------------------------------------- /llm_nomic_api_embed.py: -------------------------------------------------------------------------------- 1 | from llm import EmbeddingModel, Model, hookimpl 2 | import llm 3 | import httpx 4 | 5 | 6 | @hookimpl 7 | def register_embedding_models(register): 8 | register( 9 | NomicTextModel("nomic-embed-text-v1", "nomic-embed-text-v1"), 10 | aliases=("nomic-1",), 11 | ) 12 | for dimensionality in [None, 512, 256, 128, 64]: 13 | model_id = "nomic-embed-text-v1.5" 14 | alias = "nomic-1.5" 15 | if dimensionality: 16 | model_id += "-" + str(dimensionality) 17 | alias += "-" + str(dimensionality) 18 | register( 19 | NomicTextModel( 20 | model_id, "nomic-embed-text-v1.5", dimensionality=dimensionality 21 | ), 22 | aliases=(alias,), 23 | ) 24 | register(NomicImageModel("nomic-embed-vision-v1")) 25 | register(NomicImageModel("nomic-embed-vision-v1.5")) 26 | # and the combo models 27 | register( 28 | NomicCombinedModel( 29 | model_id="nomic-embed-combined-v1", 30 | text_model_id="nomic-embed-text-v1", 31 | vision_model_id="nomic-embed-vision-v1", 32 | ) 33 | ) 34 | register( 35 | NomicCombinedModel( 36 | model_id="nomic-embed-combined-v1.5", 37 | text_model_id="nomic-embed-text-v1.5", 38 | vision_model_id="nomic-embed-vision-v1.5", 39 | ) 40 | ) 41 | 42 | 43 | class NomicTextModel(EmbeddingModel): 44 | needs_key = "nomic" 45 | key_env_var = "NOMIC_API_KEY" 46 | batch_size = 100 47 | 48 | def __init__(self, model_id, nomic_model_id, dimensionality=None): 49 | self.model_id = model_id 50 | self.nomic_model_id = nomic_model_id 51 | self.dimensionality = dimensionality 52 | 53 | def embed_batch(self, items): 54 | headers = { 55 | "Authorization": f"Bearer {self.get_key()}", 56 | "Content-Type": "application/json", 57 | } 58 | data = { 59 | "model": self.nomic_model_id, 60 | "texts": list(items), 61 | } 62 | if self.dimensionality: 63 | data["dimensionality"] = self.dimensionality 64 | with httpx.Client() as client: 65 | response = client.post( 66 | "https://api-atlas.nomic.ai/v1/embedding/text", 67 | headers=headers, 68 | json=data, 69 | ) 70 | response.raise_for_status() 71 | return response.json()["embeddings"] 72 | 73 | 74 | class NomicImageModel(EmbeddingModel): 75 | needs_key = "nomic" 76 | key_env_var = "NOMIC_API_KEY" 77 | batch_size = 10 78 | supports_binary = True 79 | supports_text = False 80 | 81 | def __init__(self, model_id): 82 | self.model_id = model_id 83 | 84 | def embed_batch(self, items): 85 | # items will be a list of bytes 86 | headers = { 87 | "Authorization": f"Bearer {self.get_key()}", 88 | } 89 | data = {"model": self.model_id} 90 | files = [("images", item) for item in items] 91 | with httpx.Client() as client: 92 | response = client.post( 93 | "https://api-atlas.nomic.ai/v1/embedding/image", 94 | headers=headers, 95 | data=data, 96 | files=files, 97 | ) 98 | response.raise_for_status() 99 | return response.json()["embeddings"] 100 | 101 | 102 | class NomicCombinedModel(EmbeddingModel): 103 | needs_key = "nomic" 104 | key_env_var = "NOMIC_API_KEY" 105 | batch_size = 10 106 | supports_binary = True 107 | supports_text = True 108 | 109 | def __init__(self, model_id, text_model_id, vision_model_id): 110 | self.model_id = model_id 111 | self.text_model_id = text_model_id 112 | self.vision_model_id = vision_model_id 113 | 114 | def embed_batch(self, items): 115 | # Split into text and images 116 | texts = [] 117 | images = [] 118 | results_by_index = {} 119 | for i, item in enumerate(items): 120 | if isinstance(item, str): 121 | texts.append((i, item)) 122 | else: 123 | images.append((i, item)) 124 | if texts: 125 | model = llm.get_embedding_model(self.text_model_id) 126 | vectors = model.embed_batch([item[1] for item in texts]) 127 | for (index, _), vector in zip(texts, vectors): 128 | results_by_index[index] = vector 129 | if images: 130 | model = llm.get_embedding_model(self.vision_model_id) 131 | vectors = model.embed_batch([item[1] for item in images]) 132 | for (index, _), vector in zip(images, vectors): 133 | results_by_index[index] = vector 134 | keys = results_by_index.keys() 135 | return [results_by_index[key] for key in sorted(keys)] 136 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "llm-nomic-api-embed" 3 | version = "0.3" 4 | description = "Create embeddings using the Nomic API" 5 | readme = "README.md" 6 | authors = [{name = "Simon Willison"}] 7 | license = {text = "Apache-2.0"} 8 | classifiers = [ 9 | "License :: OSI Approved :: Apache Software License" 10 | ] 11 | dependencies = [ 12 | "llm", 13 | "httpx" 14 | ] 15 | 16 | [project.urls] 17 | Homepage = "https://github.com/simonw/llm-nomic-api-embed" 18 | Changelog = "https://github.com/simonw/llm-nomic-api-embed/releases" 19 | Issues = "https://github.com/simonw/llm-nomic-api-embed/issues" 20 | CI = "https://github.com/simonw/llm-nomic-api-embed/actions" 21 | 22 | [project.entry-points.llm] 23 | nomic_api_embed = "llm_nomic_api_embed" 24 | 25 | [project.optional-dependencies] 26 | test = ["pytest", "pytest-recording"] 27 | -------------------------------------------------------------------------------- /tests/cassettes/test_nomic_api_embed/test_embed.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"model": "nomic-embed-text-v1.5", "texts": ["hello world"], "dimensionality": 4 | 64}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | connection: 11 | - keep-alive 12 | content-length: 13 | - '82' 14 | content-type: 15 | - application/json 16 | host: 17 | - api-atlas.nomic.ai 18 | user-agent: 19 | - python-httpx/0.27.0 20 | method: POST 21 | uri: https://api-atlas.nomic.ai/v1/embedding/text 22 | response: 23 | body: 24 | string: '{"embeddings":[[-0.0715332,-0.0075149536,-0.45581055,0.049041748,0.054351807,0.1616211,-0.030197144,-0.1854248,-0.050842285,-0.15356445,-0.015510559,0.00447464,0.1352539,0.21362305,0.08654785,-0.24926758,0.008651733,-0.088256836,-0.099975586,0.16442871,0.015098572,-0.15429688,-0.15368652,0.08337402,0.012512207,-0.017364502,0.037261963,-0.02130127,0.032714844,-0.052490234,-0.1508789,-0.028442383,0.087768555,-0.019622803,0.0848999,-0.078552246,0.081726074,0.04486084,0.12792969,0.025314331,0.045654297,-0.032043457,0.024978638,0.014221191,0.19372559,-0.042388916,0.05444336,0.115478516,0.2878418,-0.24951172,0.035614014,0.012687683,0.053588867,0.06970215,0.1895752,0.15612793,0.08807373,-0.099731445,0.046142578,0.050567627,0.11413574,0.22363281,-0.09631348,0.12158203]],"model":"nomic-embed-text-v1.5","usage":{"prompt_tokens":2,"total_tokens":2}}' 25 | headers: 26 | Connection: 27 | - keep-alive 28 | Content-Length: 29 | - '850' 30 | Content-Security-Policy: 31 | - default-src 'self'; 32 | Content-Type: 33 | - application/json 34 | Date: 35 | - Sat, 30 Mar 2024 21:33:07 GMT 36 | Server: 37 | - nginx/1.23.3 38 | Strict-Transport-Security: 39 | - max-age=31536000; includeSubDomains; preload 40 | Vary: 41 | - Origin 42 | Via: 43 | - 1.1 42d6669d57da2de3a7f8b1123d510158.cloudfront.net (CloudFront) 44 | X-Amz-Cf-Id: 45 | - 8c8bXsfQUccfsLuvHAbH4NfNzuaATZA4mIV0I105l4don18bgZfopw== 46 | X-Amz-Cf-Pop: 47 | - SFO53-P3 48 | X-Cache: 49 | - Miss from cloudfront 50 | X-Content-Type-Options: 51 | - nosniff 52 | X-Frame-Options: 53 | - SAMEORIGIN 54 | X-Permitted-Cross-Domain-Policies: 55 | - None 56 | X-XSS-Protection: 57 | - 1; mode=block 58 | status: 59 | code: 200 60 | message: OK 61 | version: 1 62 | -------------------------------------------------------------------------------- /tests/cassettes/test_nomic_api_embed/test_embed_combination.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"model": "nomic-embed-text-v1.5", "texts": ["text", "more text"]}' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | connection: 10 | - keep-alive 11 | content-length: 12 | - '66' 13 | content-type: 14 | - application/json 15 | host: 16 | - api-atlas.nomic.ai 17 | user-agent: 18 | - python-httpx/0.27.0 19 | method: POST 20 | uri: https://api-atlas.nomic.ai/v1/embedding/text 21 | response: 22 | body: 23 | string: !!binary | 24 | H4sIAAAAAAAEA13c3a7syG0F4Hc51zNBS2q1Wn4VwwiSeBAYsT1BMgkCGH73fIuktHv7xu4+W6pi 25 | 8Wdxkayev/345S//+ssf//inv/77f//43e9///inx/o6l9f+eP70c768H6/HuWz5sjyej9fz7D8s 26 | 7/f52N4/eea1Lo9tPer5x7683uey98vb+fRSnlks6E+vfmhZ3se2Pvup7bTfea557HGu27mcRz5v 27 | y7G919rhWJ7LQog88SDec9nO2e51vAhcKy2Pdd22d/9lXY73ufcOj207Xo9HrfrYt2N5nC35e38+ 28 | z7V3Pk7H22uP7bVs63tZa4vn+/l4vN/1eXlt+/GcF57P17ac14ke57m/X73fcj7357n3n9adGL3U 29 | 5hSemS/Lsr+fz1Hbe3m+l7PU/CD5eytB1sf7ue2PXmh7P9bn+ei3H958vNfe77nvr/V4jmEuLVDW 30 | +tze207P+ezlxZP5vGyH7V5nqfmkjccyB6R7orQKD2d1xjr5djye761Medj4GO+g1o2xs+TK8O93 31 | G5vTvPhKLb8c57ktfYTn4/mitPz747E/iPYYP9usc65LLxs3sPW7t17fvuxbrWaL5/Gi2axwPM9z 32 | TG+Zlddto4Pt3Fd+3MKsDy71LiEfvIuqzjr4y9lea+n5/X6xcqmAKz/WIwu1njbr5uNuq5U2Sxvr 33 | uuw7x6svrEtptf5rXd+v7ShHW1iUP7Yqt/d7efcR3o/9Vg6/ejy3tTaIUx/rq/x93dfdxpcDvbzz 34 | 7M0E43N7jdIWgm5P/tXOub/pY68FbLburBDJn8c27r7XIcZ0z4PCJww2yny3WY6DUvrFY68QLEU4 35 | SLymD7xty7OFZnY2fC/9h1Wg5HR5gwqdYk7/WJf1yXOjR+Fz2qMke4u+53i6f3sNtrDkHhvkmYdt 36 | VyZcZmsAdMXAejiXAOnTv843J2otveMbe7/C2uf7aPdeodYyiMScy/YeTHi93u0t7/3cjvYVS1DE 37 | PlH15HWPV59zOay/M3kQ8nW8Ayij1WuD/GVZQdPrWQaBj8c+KBIQffHXOt8KOGLUOmtwUGCP3df3 38 | k9ZKQkfYN/hZOz72lYwOX++89+UprkqfIGwR2f3UC5pRb2l6O4/X9dRX4P2j9NvzWM8rIgW0oFsH 39 | QkUxP+Np3tlgN622p/K/9dgHc/mCQ/ZZntxvB3ctDOfeGXJOuYHs8eH1lC7OdnuBBxROWrbLSUPn 40 | 2JNj8Oa2Jwej1Qm4/QOMJAY24qNefr7f0HhcY90g+3G0f6+w9ZRMSix4+HDogoOHBLP6nzZkx/Qo 41 | fHsdbEmTlRG5/s7Zss3Cm/hUe6BA4/Vb+1HkBValL6DQhszr2xPYcoXSRKmrY3DdBf8Ghj0jWx67 42 | zJDHIQKEKCNKn+xh51pnlRTljzwkpDjwWPp4XijPNEzYj0tIx7I04HcITdjQMo9pV97i7iePa0F5 43 | Fj+vDaKaEo1VNxjep2e3lfVaLefCd6TrvEt+yNqBzcG5VR+GXY7GFs6QFNCvPsFzn3x/y3Jgrf49 44 | upJ2Ot3yJOE4QLOBnX7105pEZ47aVQp7gZwLrffXIZrrjW23h7/WF4AoiT5GFYuksY3DxgvXUQs1 45 | Pp6j9oizQo2cchfb1FFHcxiJY4NBsmqpQIyIxVFOaMO4yRO5ulkUMgBYSpvcgo7bYd4oV+OiRH2Q 46 | eKLoOKP+AaHHCXc6h1O4XMota+tD7otvtBw+7iCmvvAvCbv22GV6e/S/87zHy/HroVV0IAcDaF+2 47 | kcxWqafdQAA/H+VOCzYA9VqoSlvQgHbWw9NJPNGGgD0CRaUZvE7eH3PwaFpsCwjMIEh/eRIWzvWX 48 | xwqWZaMsDGJ2mp3D0gB6cKeEb3AkTYm0WYHmoGYh0EsCDcxZDHLL2M0yd0i6hzW0lDHmcBsZsdhP 49 | /pBgBgf9FDaM7g56O+TJDiXjG2uD+LWUTV7y9DjGxvroTP1F9LwoO0IBHsEGpLKHTY4H56zzyjaS 50 | 0kAAHFt9rz2CNQAvnyE19jj+Cjdfb7mnlxKJJx7eoqCWUcLYFuUNT6jnyIRFNngtKNbz2Whhi4Ov 51 | 1I6L17l0fcbaD4S0JFz5To4VSQ4fB+d3D79k8dLaCZ+WwQoZbjuu9AcnWL0ewr2gyGgQU9j3K+DD 52 | /pfEXQyAoDFVo8tbHmSN0geMPp7ZvOzHZC9Udnb39jKiiFS589xQM6txgA6j0vuOwbzOsZsig9Dt 53 | wIK+ADevyIqgZbi+ykKp0DAp5HfkuIThCl8cIQXHehUaTzXVQ+1Ukj2PVCZjdUXR/tonvDcecSJQ 54 | NvwGGcthkwtkTgn75ZAeUqcJOZhT6woLTBl+tzCbuixOl+feKB7amc+LrEjNo32CoRkdpEgdz2i9 55 | AjpHnppO3OwSwBPOlppho+io3CoTYoCdG6rYe8ifdgFHarHa/IOsCEE5gOe0HriVZ2bzM9EyXqrm 56 | eo+zWIlc7fGkE/jgwQaEUUrV4SDOLs8N0mAHj/HduySI1KCrkltesQye0iiugjwEcetDsn1Dvzxz 57 | 133tJO+XdTv1vpSQ6zAuTqXejRxZp0zh3e8A5Svf31tuePp0nDqDDCvOJIM2H04N9QfDKRb+lI6d 58 | Dv/phzwehGppYdjJ5+pEVQy2V4j9Z86Xf/8Gr+yL/k9IpApWko8plJ+T7THNh4Q9EZUK98qciadT 59 | gZN1Za1XqFDtHZ58+vfSVDEdsDuuQm3cPY+Jcvl1UjJyT23h7jQXOw2J47PKkoMx80a52Xg3eXHg 60 | dimOySNrcxX1VwZHcz9iOVggp5d+Ijk06PBXTrBbCSiUeODw0nQojnDsHISkB0M1FIBpZhtA5Uhk 61 | aY6/LBBub/+HxchLCe4BYDE6RJW1KNpkKlydFfGe41mfkfsppfSOZpRyAwMy4WxdmRn8tXq3PTXv 62 | mG3bxX4oi9UO1RwjdIw7rlxdiwFIqWXWokStkK6ybvaZ0373E1XWW1lXayHSK5jpPUQZLCjhtRmq 63 | GZS3pR6pulMUHvhR9iSNvEBOC0+3Ukte5zASwhx9k0G4cv4dlEuvSjefVW0O1T6Ge6AC05gAsy/4 64 | mGcwMAIKlBIKT4iA8levBRiGU6Ns8uWVH3lvYKilQiS+KigR2RS7lHI5fH150+iwy0+GvqY0c4Ds 65 | yOG4Y6sXvwWaFJ+TXETWZ3lMSB1z9OCqWigPrcwu8Fr0HdtVctW/Y8cXWMk0r+YOQAWUiuDBBUzp 66 | guSr9LCmoIOTlJWFZFYRVwJRspQ2BE454GOvY/GlyE2OrLFRBKWkoNS0gPLP1PdGFyaApgbwBxlb 67 | ZDXwAFLqrn0lTmHVrDXqQcCHIjMfYlWn1KuiPlHXnvL2fuIt2zF8O8EnX8FopKgRWn9uFxT9qirV 68 | cfpLNTOmQJEsn3hRO4rCWMSpS3JORnu9lss5VEZK3XrMeZDGjiOcARB3cv1Ell2e1yOaANNWI3Ab 69 | l19ia41Yge1TrOZAySMYXVhYjqc1ANXHHx4H7l6dknBs9WfLEbsxfR/w6IKyd7x7K3UQQSiNztm9 70 | AXn6sQUBEtFlD+6kUSQ9Z3vt1tTllY9gMvccrEB342CjLgD4SJHekSBn0UZJv9De1ixDv8CJJ5+H 71 | Eu4STh+xOrON6RikTFogIM7JNTagwiv3pYGM4bRMk+PaHx+HqO2ooE6RV5995CstHHATBw1FUQY5 72 | +9BsioRPU4iRnpg3mI58DicIsewSVmNQjdvp4WoQ17FBqnTdNgDPeiC2z1+CWroKTVUV+l9wT15h 73 | MHwH1aXQfkPiTvO0dqcEuh7xtaC1QTtuPtsDKenwlBIRsKgW58CQ1xtejy9VH29wWHaGt32mz7pM 74 | rKRaLDngIMDrKPqs14J0WHbWROCTCfsjuOLvcwRUbCiekNGHvTplONoFSzAmCa5EO+07cSwnoPpz 75 | 4tTPUkwtWkCsqZIv1IUUXM1eXFGS6kZCEjlu3keQFZJt6/xIHuDk9r1Yt8tre8lfjKm6Yy8+cr4Q 76 | t/oCFH3p/KFtmp55OaqgxB0QtbL9C596lVUwZgy6y7Q4IBi+Kjs4dY0fqvmUejxHP6UnZcqs9NFX 77 | CqlQ6uchvsEfLvLxCTDfSjvdQjXmVMjoIjrXNdga+bCUPtMLk09bpGRXay9Xtw4isGb9O8KhoT2g 78 | kuYeWtRoo0W87hOiYO/ZtZbOsAw1VCmddxyoQ7qLzaFNachfcQW/tILKNIUf4/AqORjdUjg15C3N 79 | Sh8c+HJrmpGM2i34OxzuXCpDxgdHmzMvqnOq/AqW6gtyKyI7wKosv6ocrgNERjcKbuOW7h/dRVK9 80 | b4KB4bQjwXcuc5GYDLtgz3jPDR15SxwrV3Q3yqIqkZPTjkV0V5y7/5CO9ORPrAlGi+u8z7GrE+Yj 81 | pSishu5CNB3BxkONOI/V4zCSL1+K/OCSNSG44ktNIYTrBfU9E3aJxw3YczLoNeqJEBy8bBJRwz3T 82 | 46rPEvLzosrftHjV9qUCjpNxwux3gMMWFt+HwBftvjhKvaL8ct7SzReHhsr2TsFXm4NYIFOxrPCD 83 | 0ZfKkO+alJAWDVNwTwKCR8qwq/7Hkk8vtT1REwDUWPKZa0ABdn2V047YLlQy8ljhUqeSvzhAOvP2 84 | 7FZU/fuitYIiVQzRAbwr99MVsmp9/OjIvuR/eNEvInuyZQfE56wI4XBQUVMiSMA6l1cbQDvBpKA2 85 | g554SqcyGVwquir6j07D3ULJWlj5B5JzF7xlKAhWpfNZFkeSAPgoLRXe9GXx+7tqFQ0h4OXxF+dr 86 | hak7NJ6uOEUL0/6Pla5Ja+TIBEzTpA8I7U0EZ5j7GQDaf0TBW+q5u0bIPipoRHkA8cHZBNEUQfq3 87 | Vu+EnR5fpQyv3JVvBAAyKRJLsK/hc8Y1kH1CKOFnjzHDJ5XS4GnubCkp01RGQshaNbW9RpNGmxCx 88 | CRO3lsZheGlYrcB9OUeOArwIXxYNLusOlNPAJ64/5Y7GscoHWa8NDbNUS/0lpQBkqC+aWECotSrV 89 | 61A0WjEH52g/mxl11oEKSZzj3WgjSlBb4+q6JNPqJLL6u1sMNtCq5LFeV1f1fC5LfZJkaUF+GiTQ 90 | f8XG6pzfUhX24q0+KbgTtN1M4wcyfFNv6A+prn72yi2FRWkgvReRVGLoy5cjEAMu3sMIUN/ZLCqG 91 | tCmrRg7ro6mtfDGAlPccUyESajP8WI6Y0LjLuHLwavFmYlWH0gwtVIooOsSQqP3A7GbnY31wJcs9 92 | lOCF78yZs5YqzTkgYL7EhWqyU7soLzUrJgYzEGOCqQNwrqpJ+y1cpEbYtR4fu1McdstlrzscUpJd 93 | 24oiR56fsVb667hq5AdHcYLmbTrSSv7SRSoIqNxn0SFQN09E6jdUY6DkZzgstv/yjUXpBKQ6bu33 94 | LOKCVCkNB26v09yBFQ3P6QycSuSIJbym16Ys0bS5Op36CDJQOayI9Xlinnl1W1qOw6H0fCZU6LOm 95 | RhEXrJjTT6ZX8Pl6Ab3ClRcO44Es6eCWr4EHrqO50Npi4qtipNuI3ikPLtflkTz1ObVMX1vBWofS 96 | 8uFrEyW0kGL3H7ist52Dd89tmI+EArG64POMVvjLXHMsoglvFtqeknl9zWjrvOQr9M7ZWV8LqY4h 97 | 0lWmrSCdAkFa9sfb0kDoVW+uXAtNcyCfYWUmrp2qJbtw3pxaieWiUKfErwZHvfFpA6MvjK6JIq3y 98 | 0HYyNZkauAMMZQpwlvOByrRBxsdqANuwGxxLiZi9uUXwJB8RwFNjr0+XDigW3LLmUgM3qecxvqvu 99 | Q275xezG1sqkizGazKblU3Kkc29CXp8hfGb6f/gp96kgKgNcQ8bx3Dwm8voySulA+ImcksQ1oa9i 100 | hxtnVjHWC99jkdqFTHUto744ly6agrEfLCNf9T5i6/g5l3X1MTt/0GAuqOSfEUHXuSZ5eBryltJF 101 | VSZ+TWG5BAAb9kghqHK34jkqkjHjHyLdSGZ6UqwyO9Ct9sY4pHp+S11eB1dfmuaXg8lh4RA9Abq5 102 | QT2Fucotna7SHE+5U+/f1VUe4wic+OpaaBwggb2LUsnct4P0czT7rUXJWZ1juhB8MFOeRj5QB0yi 103 | q6AKXpiPAoYrTT0MRgRT/hm3qNlE2wW1To+4viB/PG9A5B5weuWaSOYMaZ5ij2WXlE8OXp95wTE8 104 | E8m9u3RcgyUubqsnv10NdyNA60x1JGLuDn9m3ry6MIda+vpKzuMugJWHlzskZIVNLbpjOEpJAv6M 105 | bEtCDCZ3dRpMP4JPX+qCfRJ4qHxoBW75Q1ap+xHTOP9qhghOXLgOXPcO70aXPkh68+0An40d3Ehw 106 | dW9DJaVMv5LKR0Wcux0IxKQorAH3aVipYewlqry9861JSleNQ9h7AOCzZlEu4+QML9Ti62oAzwUV 107 | zccQScEyCBUuoRPZp2JQ1LCxlRDIaD8Fc5PNs9nVA483xKUzUa2/eB5tayJkpqv70AbhUgrKesRw 108 | l5M16nFIJGzWN5G+8OVb+aXPLGCmhLUiN5tCEFmS1ydMJb+7/3Iz3RIQbqhhWyFf01+0K82iNjUm 109 | j9eVH8l3lrrqQOHjktL8AdCkvVAx8HW5hX4MsKY9bUWReA1WxAMb1wu5JZmKv5cyQcDu7kTFRNoZ 110 | Y1Vj0Myuo2gFsOi50pzE2iaS/FTJ3cdEE5ytt9Bd8895UYTR5dWfBrpgphq1GSTIzoPWAk4Pdwh6 111 | CqMUFXlfpRIcKCEUoHUFoixfrdgLfy7u5AV3jBC3hlgmAUzKvNabwkpEdTCHr6AHc6RM2XluFhYV 112 | YcGtW+oH3iWHlOXKQ51JMYDitGMC0b7y4tXvd2Q8cTfCvia4OZLmoQumPd4zq7N1q61Y7tXqlIDM 113 | oCTX1gIPiROXWCI9UdJycXTQ1c4tV+BFbaVMZCB2v6A60CoQHlkMW3OsucqVgjq8u54zwuyrhXnq 114 | g0SkRjIvbHgz4QUe0+1jxC029II2482QUnCbTY4fpb7HnfKQnBqLzDEkT+7WWwtq9G5ggLsKtiEY 115 | iFCIRF7/HPehLJ/DDLzWCo1UnyP173VBRgaoS9aSeDRUx9dJDsAnnWJJ1D2+xS15Y2crUXMHIfQC 116 | GNMxuAu7RCTN3/2ojOEr2VX8Y8JySVP0b4hzZcp6CnpQa+suA+lsWjq6Jk72SM/0as1JKq5XNWth 117 | 3GmKeCjFqbQ8NCeXEpH8XkktHJ5T4lZ92jGpRg5VKfjlAJy00w6vko1mVCRzWGewyOhWr2kcC7SA 118 | 3LbBlbSyBVuqPqfjlj6ZoUG5YjfxLu8TkHdzBzyApdkEPqIUjdp8T/u321uZdtxFCN8CcUPq0vZX 119 | HFbwcHAxMpNkZAqpL18E+Oq1+XfMTNEzAablrj92dcRK3Ltn+1W0SDe5udtazDUJuaTPbg+3x8aX 120 | r11ikORsXlOufF2Oqn8PoDfQwMs0RIbxGZFx2C55CC4kJgUQVnz3Fl/Mk0hfc0hdZ7Dd+IF6hyz2 121 | 8/f8u2zjckCGJ2SiWkCaOj8y+eYaYTM5tDVdxbIZFM7N/Dn2t6kY38H5h3l8uz4IVt0qG11hhYGv 122 | RoHMEVi3l8vlJZP+xhMormdce1ZZMTTks0thEuAaUZM+mYzDV9KA1fSWU2A80t0IK4dx44a6mwvm 123 | qHhh6qcKh7Q2EI9Rs1Sg89Nqk7jpZKRIIcB52ifdPEV7ZsilvaiMmSi4K7xSdQo+ETn71NWMlhJ1 124 | jMj9B7QEm+jCRbWQZt9ka8TMvmUrKZj3Iyr1joJZcuqMKwRMNybY+JUCs9NDyqEKzxzZzQo9gssG 125 | H/yNDwC/9mMwDvy6sA6xuhyOeyNqQ0BS1tUkv46Ya6mXvhkcmwnvsKNYwRXmGgyv0WjLhdjYyMAp 126 | jfo6yfeBtopWeplpkuo6Shr+lY68oClikEuD6rvJfDK5zl//tEBdo1Btf8JFVWml8BgOse8d8691 127 | dyYHoN7cPshHzgRcRhW4WLdi8xcZibNldpo3tKfU1LWHDwCh40ejykC0YTwtNqSiKUOuUSe31XZX 128 | q9pC1y2F/DuhM54d3MdjsJWKBDcyPkYs9z1nr1C7zsn46t194qRwuySS+LgZahOhDXHxrz5AX8Cp 129 | g8GY0Pw6DAWECrUyXO9ipSbL10808ob85FhTZedOHluUoDzNhtNfkm7S9PI8d3SvdghP3DAE7278 130 | MMVVCqT9qh6ql0rZV6pOOuZK7fifnYs0mojelaWuwNskoi0cNJiGo9sLuk6N5sj818xaKtEx6x6x 131 | iKvJOHlBuvw6oUnHmYfUopIeKjOICtlz3U7glEMDlLu0UiTdzQ7qMACZ7KN5kNuVdUCND8zoGv8E 132 | gGiltpEK0tGtz8opQNnoKBEAalOBfuqDVyN6KRyH2SoCpuDIHP0+yLcbham/WKskkVvJOJyMO0tr 133 | BanfohysAjiHbk3AwQyWWxLkJQ2E6EGRgKZceRDEuhfW1xO4QS4pV/ijgBqnV/Ibt6zY0ANIX6pU 134 | ypkmDxLwShHGU1hY24NINRQpKWSogM/Ih4gjWOX30KDjcIIMOes6Q2mOCl+M9eMesVtcKQ0rUkBx 135 | +kCVjnkIbU7LgJPcXiVTpoU2CVwCdfF0jBxLDmJzsa+5HqGqu9bvpJFnwToIhiwmmKYUMtwln7mw 136 | wJvr//p1Yrw3IS/fr1DTTmbBfOSQUFDFny93gyl/SJdSdLSmhEB6aPNULmnXsW86nY3Dm1GSeubq 137 | xdRCwDLNzxIU1cCGKi9LFV901qkD+72qUqCuH0Wka7hVb2NedhmRZFOlSv49ZYsIaulUGxkS5113 138 | 52+2/g9c72P4lkQ4NZdSVhHazgfg1IsDQAArN6hKeVxU4JbyZChXFHOpwXb4ES01XZaoDT1aIvlf 139 | 26+TWG6dGMkO07hGNTmDNogCtHYQpqGrjRjSoSzUL4QrSXSjyrSa+EO2FpfcvdtsBvu511HWxaI1 140 | FUtWbZnk/3o85EcK693u+LUOFoDzzWboF8dvwM9YKAEXScNIM2L00SV5BL70xVNk8clwcRbZoh5n 141 | L/TqSpap08Bm/2XuCpQJ8erccKvTZBwxxdBnDr04XZ6Xf7RSpm342aMkXhqpWYc/f5W9GX0L9XaY 142 | pERQWg6DvOTaSB3CzIi/dUin+ZxuWa3kRgUVtOJdtEnru10Ms48CSqRpJpWO7MQ1+m2042u+q/jN 143 | WrUd6yE+bcLUUZqQtVIabXMDJyII0VJLeipXRsRL0/3t8JdIVDsTYppEQnpQQkrDSERaL6CrjOn1 144 | HkpkpHU+G85d/FWFww7jA98YUH6bJBA6RrkKOw41q5723I2nwUySepdcNosjsIbSKW2HeptZQO9Y 145 | D3bK4H2Sb4Sbge669GblpekP/I+VNTthWG1C1xQziwlCLlK7K3ZDEuu4YeHdqs9iwquvg8djaqzD 146 | pOUZUiGSOBwzl6Kr5ZN3ao/hpbKG07QLGAenfVRv+//7FhrAYKtpIgJ+VeuVnfwFUky2JokiWxjl 147 | LDzcYqNIyrbg8FUNan31OjDkTkO4zqXPpiQpCPlkP2kqXbUF49bQsJ7XFYTF4+GZZNyNAyo0pGlt 148 | wcAQvJKIsqTtVM+lubrh1NGver1/e3297QwwxkWxy5tc8uczV62ntFEb1bpMgOpLL1k28627L6fj 149 | Dgx7uy/gzaglc4C8/NlnSCdMKpwEgQkpv8bFq9yY2isJj2t0yOsGBLiyFPJ9XeOUXFPmjo1l89Z4 150 | yZcKCYcooe7xRf4y8+O2Xi4lXAFSGaNfMHRQ0M+R7iaOlzlVfrJ71U6cVe0Wqe6i3GfIoVK9LrDg 151 | SRJfa03Qp5NWYkiAtNPK1MhIQ7/UzA0MzPszv85UeMJUSwcPHvTJ71YAZL1/b56FPyu1XDB3VaqB 152 | JQVQ2H7tkuvR0KuhQQWIdIxgwB/GXY/pJoe2tpgudimFek9tYYDW1iWvfuF4xrefdKcKmkJLSwiK 153 | X8Cm86IwHC7+2Z66KUAUKR3WVb86l+EPQ/ZZFIAZXI5YiOnk0mAaH2/8uocdnx0kfs5jOh6u1G4r 154 | QaP9kRvU2VcDU+egfeGGxAiR5lP/JKZEsl1mB3nnThP1mOtEJBwBe4TlGQwD1ZlTI5DSbBvd0MDp 155 | Rhv5QXyPye8pjXf9JuBqZotO1XOrPnOraudnW/cR1M7DYjDaULc6zwfK5bo6LGxeGSzFH/2MppxY 156 | IlUvFBQj1nXxoP3rYxb7vcGlkksdUMrgAsVd8yXXASuL+Xx3N/KHa2zkcpjwnO5dqMHVh46/XVMn 157 | xFKIjPfdJCPLaFPmh42Tcr8u4H/78Qx1aNe2nihMapl6DwKrWNr3QxO1UuoIX9a1BeQj31y4k/zq 158 | KljFjgSbH0Bd3e7cvsuNc+8gVJDjatsrOwg9sfPxCy2k1eLNIvFSFKTTouJZUE9a9Etsxmmi3vdt 159 | p8LLZAA61XbpwThACZ9JjiyTf//4ue43ghTPz0iwT4GaZOTWb2MMDS45hemwocQAzRfQfzO960H5 160 | gUyfThb8uiYF4eD+EDeeBj8vnBIUaovaX4NXe7IPTiYQUllGdyBtgzqGYstJZyh138oq96q+0hjA 161 | BgrJdltBpFjsZe9WoCPJdjzgy5gM1kMplJ6a5/fiADljt/YF50Y5uoGuSyRspo9PbLQIUkQSqUyC 162 | vEiDngyvlEn9RSzkjlid0GZq+ulYpRxxz2/A6/PXVzavGzoRWAksgdXbnyTFAS08IZff9uQOSUki 163 | CXPrYU/SvNRZLgYzdWWHhJpxGQlOGGhA9IWEHORme3WqXMgp6IAITqscqD0wuNZQXuDC9+/LVTNk 164 | Vwbn5OmA18+RfZZwzHFbCVenrXYQNcLtgg631WzT51CJXchNwC92kFo3npHXZRWid6GcPgzvaZbC 165 | F+4KOn34JKzIdF0881EnNGSwbITECLRaEhvnVXPRlJfC9Y4AIErN/VCaxjUMixAgEuUYBqZakdGm 166 | EkXNzZ0m0ZeiJp9j16neSkuEC82rzyh06srSjHaKRFG2Y2mUrZ/HOyp6+vzXGKWUkR7RhJibx5hx 167 | h1Lucl8XuHMRTLSPq6SGDFbUKdJkTwO6vmG6uShRn13FBO9TySPw5oxA08EVQXyojMpW9SMi/5re 168 | DEJQzt9uMkxhElpt9rn+Z4AqW1KpNKyNa2RN3DqznT709eu7/IG+JZnWUvqtU0vh0Vyvn9dUEWuD 169 | p99oiQrAyTq205hKV9qiIBAHH3cwQvKTh45ALRNY0KV4/wqlmxeSZ1/RL8N93twhancBLRs/4WVX 170 | m5TYMwcKJMm+5x/+8NOPv/z6x1/+/ON3P/7661/+9G8/13+r6ufffvm/337+3+Wf9h8//fif//6X 171 | f//lx+/+9uM//+vXv/znb//826//8ctf/Zestp9+/Pbrb//y569/+Pvf/x9FjFZu7EoAAA== 172 | headers: 173 | Connection: 174 | - keep-alive 175 | Content-Encoding: 176 | - gzip 177 | Content-Security-Policy: 178 | - default-src 'self'; 179 | Content-Type: 180 | - application/json 181 | Date: 182 | - Thu, 21 Nov 2024 22:04:24 GMT 183 | Server: 184 | - nginx/1.27.2 185 | Strict-Transport-Security: 186 | - max-age=31536000; includeSubDomains; preload 187 | Transfer-Encoding: 188 | - chunked 189 | Vary: 190 | - Origin 191 | Via: 192 | - 1.1 6db0e3fcf85d00de1ac587c2611daca6.cloudfront.net (CloudFront) 193 | X-Amz-Cf-Id: 194 | - rtctqJBxacTaNTeVckjnztCHljtHcD272sHxt8EC6Kuv95hmoYsiKg== 195 | X-Amz-Cf-Pop: 196 | - SFO53-P1 197 | X-Cache: 198 | - Miss from cloudfront 199 | X-Content-Type-Options: 200 | - nosniff 201 | X-Frame-Options: 202 | - SAMEORIGIN 203 | X-Permitted-Cross-Domain-Policies: 204 | - None 205 | X-XSS-Protection: 206 | - 1; mode=block 207 | status: 208 | code: 200 209 | message: OK 210 | - request: 211 | body: "--00335af5c9a5215645d9f87cf0f4fbbd\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nnomic-embed-vision-v1.5\r\n--00335af5c9a5215645d9f87cf0f4fbbd\r\nContent-Disposition: 212 | form-data; name=\"images\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\n\x89PNG\r\n\x1A\n\0\0\0\rIHDR\0\0\0\xA6\0\0\x01\x1A\x02\x03\0\0\0\xE6\x99\xC4^\0\0\0\tPLTE\xFF\xFF\xFF\0\xFF\0\xFE\x01\0\x12t\x01J\0\0\0GIDATx\xDA\xED\xD81\x11\00\b\xC0\xC0.]\xEA\xAF&Q\x89\x04V\xE0>\xF3+\xC8\x91Z\xF4\xA2\bEQ\x14EQ\x14EQ\x14EQ\xD4B\x91$I3\xBB\xBF\bEQ\x14EQ\x14EQ\x14E\xD1\xA5\xD4\x17\x91\xC6\x95\x05\x15\x0F\x9F\xC5\t\x9F\xA4\0\0\0\0IEND\xAEB`\x82\r\n--00335af5c9a5215645d9f87cf0f4fbbd--\r\n" 213 | headers: 214 | accept: 215 | - '*/*' 216 | accept-encoding: 217 | - gzip, deflate 218 | connection: 219 | - keep-alive 220 | content-length: 221 | - '442' 222 | content-type: 223 | - multipart/form-data; boundary=00335af5c9a5215645d9f87cf0f4fbbd 224 | host: 225 | - api-atlas.nomic.ai 226 | user-agent: 227 | - python-httpx/0.27.0 228 | method: POST 229 | uri: https://api-atlas.nomic.ai/v1/embedding/image 230 | response: 231 | body: 232 | string: !!binary | 233 | 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 307 | headers: 308 | Connection: 309 | - keep-alive 310 | Content-Encoding: 311 | - gzip 312 | Content-Security-Policy: 313 | - default-src 'self'; 314 | Content-Type: 315 | - application/json 316 | Date: 317 | - Thu, 21 Nov 2024 22:04:24 GMT 318 | Server: 319 | - nginx/1.27.2 320 | Strict-Transport-Security: 321 | - max-age=31536000; includeSubDomains; preload 322 | Transfer-Encoding: 323 | - chunked 324 | Vary: 325 | - Origin 326 | Via: 327 | - 1.1 9ec602570ed1767b4245c59d0b4b1d70.cloudfront.net (CloudFront) 328 | X-Amz-Cf-Id: 329 | - v8GAw0bji4GwLGz5e1qYJIwGl8rO4AC5OKcwNhiMxoF_J4aqWcrXyA== 330 | X-Amz-Cf-Pop: 331 | - SFO53-P1 332 | X-Cache: 333 | - Miss from cloudfront 334 | X-Content-Type-Options: 335 | - nosniff 336 | X-Frame-Options: 337 | - SAMEORIGIN 338 | X-Permitted-Cross-Domain-Policies: 339 | - None 340 | X-XSS-Protection: 341 | - 1; mode=block 342 | status: 343 | code: 200 344 | message: OK 345 | version: 1 346 | -------------------------------------------------------------------------------- /tests/cassettes/test_nomic_api_embed/test_embed_vision.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: "--4e6a6747cf12279a07ce62e9beea86e7\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nnomic-embed-vision-v1.5\r\n--4e6a6747cf12279a07ce62e9beea86e7\r\nContent-Disposition: 4 | form-data; name=\"images\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\n\x89PNG\r\n\x1A\n\0\0\0\rIHDR\0\0\0\xA6\0\0\x01\x1A\x02\x03\0\0\0\xE6\x99\xC4^\0\0\0\tPLTE\xFF\xFF\xFF\0\xFF\0\xFE\x01\0\x12t\x01J\0\0\0GIDATx\xDA\xED\xD81\x11\00\b\xC0\xC0.]\xEA\xAF&Q\x89\x04V\xE0>\xF3+\xC8\x91Z\xF4\xA2\bEQ\x14EQ\x14EQ\x14EQ\xD4B\x91$I3\xBB\xBF\bEQ\x14EQ\x14EQ\x14E\xD1\xA5\xD4\x17\x91\xC6\x95\x05\x15\x0F\x9F\xC5\t\x9F\xA4\0\0\0\0IEND\xAEB`\x82\r\n--4e6a6747cf12279a07ce62e9beea86e7--\r\n" 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | connection: 11 | - keep-alive 12 | content-length: 13 | - '442' 14 | content-type: 15 | - multipart/form-data; boundary=4e6a6747cf12279a07ce62e9beea86e7 16 | host: 17 | - api-atlas.nomic.ai 18 | user-agent: 19 | - python-httpx/0.27.0 20 | method: POST 21 | uri: https://api-atlas.nomic.ai/v1/embedding/image 22 | response: 23 | body: 24 | string: !!binary | 25 | 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 99 | headers: 100 | Connection: 101 | - keep-alive 102 | Content-Encoding: 103 | - gzip 104 | Content-Security-Policy: 105 | - default-src 'self'; 106 | Content-Type: 107 | - application/json 108 | Date: 109 | - Thu, 21 Nov 2024 21:25:12 GMT 110 | Server: 111 | - nginx/1.27.2 112 | Strict-Transport-Security: 113 | - max-age=31536000; includeSubDomains; preload 114 | Transfer-Encoding: 115 | - chunked 116 | Vary: 117 | - Origin 118 | Via: 119 | - 1.1 b25dbab50c2d4b34d29539472626bfbe.cloudfront.net (CloudFront) 120 | X-Amz-Cf-Id: 121 | - 5PEOQms1e7xVNksGdgCsq8ianKBX6QE202VP-YWOHfXeigD39jMK3g== 122 | X-Amz-Cf-Pop: 123 | - SFO53-P1 124 | X-Cache: 125 | - Miss from cloudfront 126 | X-Content-Type-Options: 127 | - nosniff 128 | X-Frame-Options: 129 | - SAMEORIGIN 130 | X-Permitted-Cross-Domain-Policies: 131 | - None 132 | X-XSS-Protection: 133 | - 1; mode=block 134 | status: 135 | code: 200 136 | message: OK 137 | version: 1 138 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture(autouse=True) 5 | def patch_env(monkeypatch): 6 | monkeypatch.setenv("NOMIC_API_KEY", "mock-key") 7 | -------------------------------------------------------------------------------- /tests/test_nomic_api_embed.py: -------------------------------------------------------------------------------- 1 | import llm 2 | import pytest 3 | from vcr.request import Request as VcrRequest 4 | from vcr.stubs import httpx_stubs 5 | 6 | 7 | TINY_PNG = ( 8 | b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xa6\x00\x00\x01\x1a" 9 | b"\x02\x03\x00\x00\x00\xe6\x99\xc4^\x00\x00\x00\tPLTE\xff\xff\xff" 10 | b"\x00\xff\x00\xfe\x01\x00\x12t\x01J\x00\x00\x00GIDATx\xda\xed\xd81\x11" 11 | b"\x000\x08\xc0\xc0.]\xea\xaf&Q\x89\x04V\xe0>\xf3+\xc8\x91Z\xf4\xa2\x08EQ\x14E" 12 | b"Q\x14EQ\x14EQ\xd4B\x91$I3\xbb\xbf\x08EQ\x14EQ\x14EQ\x14E\xd1\xa5" 13 | b"\xd4\x17\x91\xc6\x95\x05\x15\x0f\x9f\xc5\t\x9f\xa4\x00\x00\x00\x00IEND\xaeB`" 14 | b"\x82" 15 | ) 16 | 17 | 18 | @pytest.fixture(scope="module") 19 | def vcr_config(): 20 | return {"filter_headers": ["authorization"]} 21 | 22 | 23 | @pytest.mark.vcr() 24 | def test_embed(): 25 | model = llm.get_embedding_model("nomic-embed-text-v1.5-64") 26 | result = model.embed("hello world") 27 | assert isinstance(result, list) 28 | assert all(isinstance(item, float) for item in result) 29 | assert len(result) == 64 30 | 31 | 32 | @pytest.mark.vcr() 33 | def test_embed_vision(): 34 | model = llm.get_embedding_model("nomic-embed-vision-v1.5") 35 | result = model.embed(TINY_PNG) 36 | assert isinstance(result, list) 37 | assert all(isinstance(item, float) for item in result) 38 | assert len(result) == 768 39 | 40 | 41 | @pytest.mark.vcr() 42 | def test_embed_combination(): 43 | model = llm.get_embedding_model("nomic-embed-combined-v1.5") 44 | result = model.embed_batch(["text", TINY_PNG, "more text"]) 45 | assert isinstance(result, list) 46 | assert len(result) == 3 47 | for vector in result: 48 | assert all(isinstance(item, float) for item in vector) 49 | 50 | 51 | # Nasty monkey-patch to work around https://github.com/kevin1024/vcrpy/issues/656 52 | def _make_vcr_request(httpx_request, **kwargs): 53 | try: 54 | body = httpx_request.read().decode("utf-8") 55 | except UnicodeDecodeError: 56 | body = httpx_request.read().decode("ISO-8859-1").encode("utf-8") 57 | 58 | uri = str(httpx_request.url) 59 | headers = dict(httpx_request.headers) 60 | return VcrRequest(httpx_request.method, uri, body, headers) 61 | 62 | 63 | httpx_stubs._make_vcr_request = _make_vcr_request 64 | --------------------------------------------------------------------------------