BGE Base English

Normalized 768-dimension English embeddings, over a 512-token context.

Embeddingsl40sBAAIMITBAAI/bge-base-en-v1.5

What runs

This is the whole app. The entry names the model and what serves it, and the build turns that into these files: there is nothing else to write.

model.py
"""BGE Base English, generated from a declarative template."""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field

from runware_serverless import serve

MODEL = "BAAI/bge-base-en-v1.5"
REVISION = "a5beb1e3e68b9ab74eb54cfd186867f64f240e1a"
CACHE = "/weights"


class Request(BaseModel):
    # An input this model does not read is a line the caller believed was doing
    # something, so it is refused rather than dropped. Without this, pydantic
    # ignores it: a width sent to a model of fixed size, or a misspelled seed,
    # both come back as a result that silently answered a different request.
    model_config = ConfigDict(extra="forbid")

    texts: list[str] = Field(description="The texts to embed, in order.")


class Embedded(BaseModel):
    vectors: list[list[float]]
    dimensions: int


@serve
class GeneratedEmbeddings:
    def load(self) -> None:
        if hasattr(self, "model"):
            return

        from sentence_transformers import SentenceTransformer

        self.model = SentenceTransformer(
            MODEL, revision=REVISION, cache_folder=CACHE, device="cuda"
        )

    def predict(self, request: Request) -> Embedded:
        vectors = self.model.encode(request.texts, normalize_embeddings=True)

        return Embedded(
            vectors=[vector.tolist() for vector in vectors],
            dimensions=int(vectors.shape[-1]),
        )
runware.yaml
configVersion: 1
id: bge-base-en-v15
name: BGE Base English
source:
  type: code
  entry: model.py
compute:
  gpuType: l40s
build:
  requirements:
    - torch==2.14.1
    - sentence-transformers==5.1.2
volumes:
  - /weights

Deploying

Deploy it as it is, or take the files above and deploy your own copy. Nothing you change reaches back to this page.

bge-base-en-v15l40ssource
From a URL
runware serverless deploy --from https://runware.ai/docs/serverless/examples/bge-base-en.zip
From a clone
runware serverless deploy model.py \
  --id bge-base-en-v15 \
  --gpu-type l40s \
  --requirement torch==2.14.1 \
  --requirement sentence-transformers==5.1.2 \
  --volume /weights

Calling it

One request that works, against the app you just deployed. The fields are the ones the entry declares above, and anything it does not declare is refused rather than ignored.

import { createClient } from '@runware/sdk'

const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })

const task = await client.invoke({
  appId: 'bge-base-en',
  endpointPath: 'predict',
  payload: {
    request: {
      texts: [
        'a cat sat on the mat',
        'a kitten rested on the rug'
      ]
    }
  }
})
import asyncio
import os

from runware import Runware


async def main():
    client = Runware(api_key=os.environ["RUNWARE_API_KEY"])
    try:
        task = await client.invoke(
            "bge-base-en",
            "predict",
            {
                "request": {
                    "texts": [
                        "a cat sat on the mat",
                        "a kitten rested on the rug"
                    ]
                }
            },
        )
    finally:
        await client.close()


asyncio.run(main())
curl https://api.serverless.runware.ai/v1/apps/bge-base-en/invoke-async/predict \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "taskId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "payload": {
      "request": {
        "texts": [
          "a cat sat on the mat",
          "a kitten rested on the rug"
        ]
      }
    }
  }'
cat <<'EOF' | runware serverless apps invoke bge-base-en predict -f -
{
  "request": {
    "texts": [
      "a cat sat on the mat",
      "a kitten rested on the rug"
    ]
  }
}
EOF
{
  "taskId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "payload": {
    "request": {
      "texts": [
        "a cat sat on the mat",
        "a kitten rested on the rug"
      ]
    }
  }
}

What it costs

This entry is pinned to l40s, which is the card it was tested on rather than the only one it runs on: --gpu-typedeploys it somewhere else. You pay for that card by the second while a worker holds it, and for nothing else. Pricing covers what meters, and the rates are published per GPU-second.