Skip to content

Embeddings

An embedding is a numeric fingerprint of a piece of text or an image. The model reads the input and returns a vector, a fixed-length list of numbers, positioned so that inputs with similar meaning land close together and unrelated inputs land far apart. Once your content lives as vectors, “find the most relevant document” becomes “find the nearest vector”, which databases do quickly and at scale. Embeddings are the substrate underneath semantic search, retrieval-augmented generation, clustering, deduplication and classification.

flinq’s models are specialized on the European construction (AEC) domain, with German as the deepest-trained language. flinq-embed-2.0 embeds text and images into one 2048-dim vector space; flinq-embed-1.5-beta embeds text into 1024 dimensions. See Models for the full spec tables.

Because every vector is L2-normalized, cosine similarity is just a dot product, and you can compare two vectors by multiplying and summing. If your store wants inner product, you can use it directly.

/v1/embeddings is OpenAI-compatible, so the OpenAI SDKs work unchanged — set the base_url and pass a flinq model id (required; see Models).

curl https://api.flinq.ai/v1/embeddings \
-H "Authorization: Bearer flq_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"model": "flinq-embed-2.0",
"input": ["Stahlbetonfertigteildecke d = 20 cm", "Bewehrungsanschluss BSt 500"],
"dimensions": 512
}'

The response mirrors the OpenAI layout: data[i].embedding is the L2-normalized vector for input[i], and usage carries the billed token count.

On flinq-embed-2.0, a search query and the passages it should find are embedded differently. Embed your corpus as documents (the default) and your search queries with "input_type": "query". A query can also name a task, which selects the instruction the model was trained with for that kind of search:

  • lv_matching: a bill-of-quantities (LV) position matched against a cost or product catalogue.
  • image_search: a text query against figures, drawings and diagrams.
  • retrieval: general passages. The default.

The instruction is added on the server and is not billed. input_type and task are flinq fields outside the OpenAI schema, so the OpenAI SDKs send them through extra_body:

curl https://api.flinq.ai/v1/embeddings \
-H "Authorization: Bearer flq_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"model": "flinq-embed-2.0",
"input": "Mauerwerk Kalksandstein, d = 17,5 cm, Innenwand",
"input_type": "query",
"task": "lv_matching"
}'

flinq-embed-1.5-beta has no trained tasks: it accepts input_type, but a task returns 422. /v1/search and /v1/rerank treat their query as a query automatically and take the same optional task.

flinq-embed-2.0 embeds images into the same vector space as text, so a text query finds the detail drawing, section or diagram it describes. Send each image as an OpenAI chat content part inside input, with the image inline as a base64 data URL. Texts and images can be mixed in one request.

# The body goes through a file: a base64 image is too long for a command-line argument.
printf '{"model": "flinq-embed-2.0", "input": [
{"type": "image_url", "image_url": {"url": "data:image/png;base64,%s"}},
"Fensteranschluss mit Kompriband, Vertikalschnitt"
]}' "$(base64 < fensteranschluss.png | tr -d '\n')" > body.json
curl https://api.flinq.ai/v1/embeddings \
-H "Authorization: Bearer flq_your_key_here" \
-H "Content-Type: application/json" \
-d @body.json

The rules for image inputs:

  • Formats. PNG, JPEG and WebP, as data:image/png;base64,... (or image/jpeg, image/webp). Remote http(s) URLs are not fetched and return 422.
  • Size. Up to 5 MB and 50 megapixels per image, up to 16 images per request. The model sees each image scaled down, keeping the aspect ratio, to at most 802,816 pixels (about 0.8 MP, for example 896 × 896). EXIF rotation is respected.
  • Billing. An image is billed as its visual tokens: one token per 32 × 32-pixel block after scaling, at most 784 tokens per image, at the same EUR 0.40 per 1M tokens as text.
  • Images are documents. Embed them with the default input_type; an image with "input_type": "query" returns 422. The query side of an image search is text, with "task": "image_search".
  • Not on /v1/search. Hybrid search is text-only because its BM25 leg needs text. To rerank images, pass them as documents to flinq-rerank-2.0 on /v1/rerank.

flinq-embed-1.5-beta is text-only and returns 422 for image inputs.

ParameterTypeRequiredDefaultDescription
modelstringyes—Model id: flinq-embed-2.0 or flinq-embed-1.5-beta. Unknown ids return 404 with the list of available models; discover them via GET /v1/models.
inputstring or arrayyes—Text to embed, or an array of texts and, on flinq-embed-2.0, image parts ({"type": "image_url", ...}, see Images). Up to 256 inputs per request on both embedding models; over the cap returns 422. Each text may have up to 8,192 tokens — an over-limit text returns 422 unless the request opts into "truncation": "auto"; nothing is ever cut silently.
input_typestringno"document""document" for what is searched, "query" for search queries. Images are always documents.
taskstringno"retrieval"flinq-embed-2.0 only: lv_matching, image_search or retrieval. Selects the query instruction; ignored for documents. On the 1.5 beta it returns 422.
dimensionsintegernonativeMatryoshka output size: 2048, 1024, 512, 256 or 128 on 2.0 (native 2048); 1024, 768, 512, 256 or 128 on the 1.5 beta (native 1024). The server truncates the native vector to the first N components and re-normalizes. Smaller = cheaper storage and faster ANN at a small quality cost. Same price — billing counts input tokens, not output size.
truncationstringno"error""error" rejects an over-limit text with 422; "auto" truncates it at the limit and reports its index in truncated. Images are never truncated.
encoding_formatstringno"float"Accepted for OpenAI compatibility; only "float" (JSON number arrays) is currently served.

Headers. Authorization: Bearer flq_... (required). Optionally send an Idempotency-Key header: if you retry a request with the same key (e.g. after a network timeout), the charge is deduplicated — you are never billed twice for the same logical request.

Response fields.

FieldTypeDescription
data[i].indexintegerPosition of this vector in your input array — order is always preserved.
data[i].embeddingfloat[]L2-normalized vector (dimensions long). Cosine similarity = plain dot product.
modelstringThe model that served the request.
usage.total_tokensintegerBilled tokens, counted server-side with the model’s own tokenizer (not whitespace), plus the visual tokens of any images.
truncatedinteger[]Indices of texts truncated under "truncation": "auto".
warningsstring[]Human-readable notes, for example a truncation.

Billing. tokens(input) × EUR 0.40 / 1M, with images counted as their visual tokens. The query instruction selected by task is not billed. A request rejected before inference (unknown model, over the input cap, bad schema) costs nothing.

Both embedding models are trained so that the first N components of the native vector remain a faithful, self-contained embedding on their own. That is the Matryoshka property: nest a smaller vector inside the larger one. Request a smaller dimensions and flinq truncates to that prefix and re-normalizes.

The tradeoff is concrete. A 256-dim slice of a flinq-embed-2.0 vector is an eighth of the storage and roughly an eighth of the nearest-neighbor work of the full 2048 dimensions, for a drop in retrieval quality. You pick the point on that curve that fits your index budget and latency target, without re-embedding your corpus: store the full vector once, and you can slice it later.

General-purpose embedding APIs are trained on broad web text. On construction language they fail in two specific, repeatable ways.

German builds long compounds: Stahlbetonfertigteildecke, Dämmerungsschalter, Bewehrungsanschluss. A generic tokenizer shreds these into subword fragments and the model averages them into a vague blur, losing the precise object the compound names. flinq is tuned on this vocabulary, so the compound resolves to the thing it actually denotes rather than to a smeared average of its parts.

In construction, a single token is the difference between right and wrong. DN 100 and DN 150 are different pipe diameters. C20/25 and C25/30 are different concrete strength classes. XC4 is a specific exposure class. Generic models treat these as near-identical because they look alike as strings, and they confidently return the wrong one. flinq is trained to keep these distinctions sharp. For the cases where lexical precision must be absolute, the hybrid search endpoint adds a BM25 leg that anchors on the exact code or unit.