# ------------------------------------------------------------------- # This source file is available under the terms of the # Pimcore Open Core License (POCL) # Full copyright and license information is available in # LICENSE.md which is distributed with this source code. # # @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) # @license Pimcore Open Core License (POCL) # ------------------------------------------------------------------- """Request/response samples for the embedding endpoints, kept out of `main.py` so the routing stays readable. These are meant to be *runnable*: pick one in the `/docs` "Try it out" dropdown and send it as-is. That is why the models named here are small, standard-architecture ones rather than the multi-GB examples elsewhere in the docs, and why the image sample carries a real (tiny) PNG instead of a `"base64_encoded_image_string"` placeholder. `tests/test_openapi_examples.py` validates every sample against the request model, so a sample cannot drift out of sync with the schema. """ from typing import Any, Union # A real 16x16 PNG, so the image samples below can be executed unmodified. SAMPLE_PNG_BASE64 = ( "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGUlEQVR4nGNUTX7NQApgIkn1qIZRDUNKAwCg0AGTz0Gc9wAAAABJRU5ErkJggg==" ) # ~90 MB, no custom code, downloads in seconds — the right default for a first request. _SMALL_TEXT_MODEL = "sentence-transformers/all-MiniLM-L6-v2" _SMALL_IMAGE_MODEL = "google/siglip-base-patch16-224" TEXT_EMBEDDING_EXAMPLES: dict[str, Any] = { "single": { "summary": "One string (start here)", "description": ( f"Smallest useful request. `{_SMALL_TEXT_MODEL}` is a few hundred MB and needs no " "custom code, so it loads on first call without any configuration." ), "value": {"model": _SMALL_TEXT_MODEL, "input": "a blue sports car"}, }, "batch": { "summary": "Several strings in one call", "description": ( "A list is embedded in a single forward pass, which is markedly faster than one request " "per string. `data` comes back in input order, each entry carrying its `index`." ), "value": { "model": _SMALL_TEXT_MODEL, "input": ["a blue sports car", "ein blaues Sportauto", "a recipe for onion soup"], }, }, "instruction_prefixed": { "summary": "Nomic, with its task prefix", "description": ( "Models in the Nomic family expect an instruction prefix on every input — " "`search_query: ` for the thing being searched with, `search_document: ` for the things " "being searched over. The service does not add it for you; embed queries and documents " "with matching prefixes or the two spaces will not line up. This model carries custom " "code, so its namespace must appear in `TRUSTED_CODE_ORGS` (it does by default)." ), "value": { "model": "nomic-ai/nomic-embed-text-v1.5", "input": ["search_query: a blue sports car"], }, }, "openai_compatible": { "summary": "With the OpenAI compatibility fields", "description": ( "`encoding_format` selects the wire format and only `'float'` is supported here; `user` " "is an identifier you invent for abuse attribution and is accepted but ignored. Both " "exist so a client written against OpenAI's /v1/embeddings works unchanged. Sending " "`encoding_format: 'base64'` or any `dimensions` value is refused with a 422 rather " "than silently ignored." ), "value": { "model": _SMALL_TEXT_MODEL, "input": "a blue sports car", "encoding_format": "float", "user": "pimcore-bpt-tenant-42", }, }, } IMAGE_EMBEDDING_EXAMPLES: dict[str, Any] = { "single": { "summary": "One base64 image (runnable as-is)", "description": ( "The `input` value is the base64 of the image bytes. The sample below is a real 16x16 " "PNG, so this request works unmodified — swap in your own base64 to try a real asset." ), "value": {"model": _SMALL_IMAGE_MODEL, "input": SAMPLE_PNG_BASE64}, }, "batch": { "summary": "Several images in one call", "description": ( "Images are embedded in one forward pass. An image that cannot be decoded is skipped: " "it is omitted from `data`, so its `index` is missing rather than shifting the rest." ), "value": {"model": _SMALL_IMAGE_MODEL, "input": [SAMPLE_PNG_BASE64, SAMPLE_PNG_BASE64]}, }, "data_url": { "summary": "A data: URL", "description": ( "A `data:image/...;base64,` prefix is accepted and stripped, so values copied straight " "out of a browser or an HTML `src` attribute work without editing." ), "value": {"model": _SMALL_IMAGE_MODEL, "input": f"data:image/png;base64,{SAMPLE_PNG_BASE64}"}, }, } # Shared by both endpoints — the response shape is identical. # `Union[int, str]` rather than `int | str`: module-level annotations are evaluated at runtime, and # PEP 604 unions need Python 3.10 — the Dockerfile and CI both run 3.9. EMBEDDINGS_RESPONSES: dict[Union[int, str], dict[str, Any]] = { 200: { "description": "Embeddings in input order. Every vector is L2-normalized (length 1).", "content": { "application/json": { "example": { "object": "list", "data": [ {"object": "embedding", "index": 0, "embedding": [0.0163, -0.0412, 0.0967]}, {"object": "embedding", "index": 1, "embedding": [-0.0271, 0.0538, 0.0114]}, ], "model": _SMALL_TEXT_MODEL, "usage": {"prompt_tokens": 0, "total_tokens": 0}, } } }, }, 400: { "description": "The `model` value is not a well-formed Hugging Face repo id.", "content": { "application/json": { "example": { "detail": ( "Invalid model id '../../etc/passwd'. Expected a Hugging Face repo id such " "as 'namespace/model' or a canonical model name." ) } } }, }, 404: { "description": "The model id is well-formed but could not be loaded (unknown, gated, or " "unavailable offline).", "content": { "application/json": {"example": {"detail": "Model 'acme/does-not-exist' could not be loaded: ..."}} }, }, }