#Vespa

Standalone ColBERT + Vespa for long-context ranking

This is a guide on how to use the ColBERT package to produce token-level vectors. This as an alternative for using the native Vespa colbert embedder.

This guide illustrates how to feed multiple passages per document (long-context)

  • Compress token vectors using binarization compatible with Vespa unpackbits

  • Use Vespa hex feed format for binary vectors with mixed vespa tensors

  • How to query

Read more about Vespa Long-Context ColBERT.

[ ]:
!pip3 install -U pyvespa colbert-ai numpy torch

Load a checkpoint with colbert and obtain document and query embeddings

[11]:
from colbert.modeling.checkpoint import Checkpoint
from colbert.infra import ColBERTConfig

ckpt = Checkpoint(
    "colbert-ir/colbertv2.0", colbert_config=ColBERTConfig(root="experiments")
)
/opt/homebrew/lib/python3.11/site-packages/torch/cuda/amp/grad_scaler.py:126: UserWarning: torch.cuda.amp.GradScaler is enabled, but CUDA is not available.  Disabling.
  warnings.warn(
[50]:
document_passages = [
    "Alan Turing  was an English mathematician, computer scientist, logician, cryptanalyst, philosopher and theoretical biologist.",
    "Born in Maida Vale, London, Turing was raised in southern England. He graduated from King's College, Cambridge, with a degree in mathematics.",
    "After the war, Turing worked at the National Physical Laboratory, where he designed the Automatic Computing Engine, one of the first designs for a stored-program computer.",
    "Turing has an extensive legacy with statues of him and many things named after him, including an annual award for computer science innovations.",
]
[51]:
document_token_vectors = ckpt.docFromText(document_passages)
/opt/homebrew/lib/python3.11/site-packages/torch/amp/autocast_mode.py:250: UserWarning: User provided device_type of 'cuda', but CUDA is not available. Disabling
  warnings.warn(
[52]:
document_token_vectors.shape
[52]:
torch.Size([4, 35, 128])
[53]:
query_vectors = ckpt.queryFromText(["Who was Alan Turing?"])[0]
query_vectors.shape
[53]:
torch.Size([32, 128])

The query is always padded to 32 so in the above we have 32 query token vectors.

Routines for binarization and output in Vespa tensor format that can be used in queries and in JSON feed.

[67]:
import numpy as np
import torch
from binascii import hexlify
from typing import List, Dict


def binarize_token_vectors_hex(vectors: torch.Tensor) -> Dict[str, str]:
    # Notice axix=2 to pack the bits in the last dimension which is the token level vectors
    binarized_token_vectors = np.packbits(np.where(vectors > 0, 1, 0), axis=2).astype(
        np.int8
    )
    vespa_tensor = list()
    for chunk_index in range(0, len(binarized_token_vectors)):
        token_vectors = binarized_token_vectors[chunk_index]
        for token_index in range(0, len(token_vectors)):
            values = str(hexlify(token_vectors[token_index].tobytes()), "utf-8")
            if (
                values == "00000000000000000000000000000000"
            ):  # skip empty vectors due to padding of batch
                continue
            vespa_tensor_cell = {
                "address": {"context": chunk_index, "token": token_index},
                "values": values,
            }
            vespa_tensor.append(vespa_tensor_cell)

    return vespa_tensor


def float_query_token_vectors(vectors: torch.Tensor) -> Dict[str, List[float]]:
    vespa_token_feed = dict()
    for index in range(0, len(vectors)):
        vespa_token_feed[index] = vectors[index].tolist()
    return vespa_token_feed
[ ]:
import json

print(json.dumps(binarize_token_vectors_hex(document_token_vectors)))
print(json.dumps(float_query_token_vectors(query_vectors)))

Definining the Vespa application

PyVespa helps us build the Vespa application package. A Vespa application package consists of configuration files, schemas, models, and code (plugins).

First, we define a Vespa schema with the fields we want to store and their type.

We use HNSW with hamming distance for retrieval

[60]:
from vespa.package import Schema, Document, Field

colbert_schema = Schema(
    name="doc",
    document=Document(
        fields=[
            Field(name="id", type="string", indexing=["summary"]),
            Field(
                name="passages",
                type="array<string>",
                indexing=["summary", "index"],
                index="enable-bm25",
            ),
            Field(
                name="colbert",
                type="tensor<int8>(context{}, token{}, v[16])",
                indexing=["attribute", "summary"],
            ),
        ]
    ),
)
[61]:
from vespa.package import ApplicationPackage

vespa_app_name = "colbertlong"
vespa_application_package = ApplicationPackage(
    name=vespa_app_name, schema=[colbert_schema]
)

Note that we just use max sim in the first phase ranking over all the hits that are retrieved by the query

[62]:
from vespa.package import RankProfile, Function, FirstPhaseRanking

colbert_profile = RankProfile(
    name="default",
    inputs=[("query(qt)", "tensor<float>(querytoken{}, v[128])")],
    functions=[
        Function(
            name="max_sim_per_context",
            expression="""
                sum(
                    reduce(
                        sum(
                            query(qt) * unpack_bits(attribute(colbert)) , v
                        ),
                        max, token
                    ),
                    querytoken
                )
            """,
        ),
        Function(
            name="max_sim", expression="reduce(max_sim_per_context, max, context)"
        ),
    ],
    first_phase=FirstPhaseRanking(expression="max_sim"),
    match_features=["max_sim_per_context"],
)
colbert_schema.add_rank_profile(colbert_profile)

Deploy the application to Vespa Cloud

With the configured application, we can deploy it to Vespa Cloud. It is also possible to deploy the app using docker; see the Hybrid Search - Quickstart guide for an example of deploying it to a local docker container.

Install the Vespa CLI using homebrew - or download a binary from GitHub as demonstrated below.

[ ]:
!brew install vespa-cli

Alternatively, if running in Colab, download the Vespa CLI:

[ ]:
import os
import requests

res = requests.get(
    url="https://api.github.com/repos/vespa-engine/vespa/releases/latest"
).json()
os.environ["VERSION"] = res["tag_name"].replace("v", "")
!curl -fsSL https://github.com/vespa-engine/vespa/releases/download/v${VERSION}/vespa-cli_${VERSION}_linux_amd64.tar.gz | tar -zxf -
!ln -sf /content/vespa-cli_${VERSION}_linux_amd64/bin/vespa /bin/vespa

To deploy the application to Vespa Cloud we need to create a tenant in the Vespa Cloud:

Create a tenant at console.vespa-cloud.com (unless you already have one). This step requires a Google or GitHub account, and will start your free trial. Make note of the tenant name, it is used in the next steps.

Configure Vespa Cloud date-plane security

Create Vespa Cloud data-plane mTLS cert/key-pair. The mutual certificate pair is used to talk to your Vespa cloud endpoints. See Vespa Cloud Security Guide for details.

We save the paths to the credentials for later data-plane access without using pyvespa APIs.

[ ]:
import os

os.environ["TENANT_NAME"] = "vespa-team"  # Replace with your tenant name

vespa_cli_command = (
    f'vespa config set application {os.environ["TENANT_NAME"]}.{vespa_app_name}'
)

!vespa config set target cloud
!{vespa_cli_command}
!vespa auth cert -N

Validate that we have the expected data-plane credential files:

[35]:
from os.path import exists
from pathlib import Path

cert_path = (
    Path.home()
    / ".vespa"
    / f"{os.environ['TENANT_NAME']}.{vespa_app_name}.default/data-plane-public-cert.pem"
)
key_path = (
    Path.home()
    / ".vespa"
    / f"{os.environ['TENANT_NAME']}.{vespa_app_name}.default/data-plane-private-key.pem"
)

if not exists(cert_path) or not exists(key_path):
    print(
        "ERROR: set the correct paths to security credentials. Correct paths above and rerun until you do not see this error"
    )

Note that the subsequent Vespa Cloud deploy call below will add data-plane-public-cert.pem to the application before deploying it to Vespa Cloud, so that you have access to both the private key and the public certificate. At the same time, Vespa Cloud only knows the public certificate.

Configure Vespa Cloud control-plane security

Authenticate to generate a tenant level control plane API key for deploying the applications to Vespa Cloud, and save the path to it.

The generated tenant api key must be added in the Vespa Console before attemting to deploy the application.

To use this key in Vespa Cloud click 'Add custom key' at
https://console.vespa-cloud.com/tenant/TENANT_NAME/account/keys
and paste the entire public key including the BEGIN and END lines.
[ ]:
!vespa auth api-key

from pathlib import Path

api_key_path = Path.home() / ".vespa" / f"{os.environ['TENANT_NAME']}.api-key.pem"

Deploy to Vespa Cloud

Now that we have data-plane and control-plane credentials ready, we can deploy our application to Vespa Cloud!

PyVespa supports deploying apps to the development zone.

Note: Deployments to dev and perf expire after 7 days of inactivity, i.e., 7 days after running deploy. This applies to all plans, not only the Free Trial. Use the Vespa Console to extend the expiry period, or redeploy the application to add 7 more days.

[63]:
from vespa.deployment import VespaCloud


def read_secret():
    """Read the API key from the environment variable. This is
    only used for CI/CD purposes."""
    t = os.getenv("VESPA_TEAM_API_KEY")
    if t:
        return t.replace(r"\n", "\n")
    else:
        return t


vespa_cloud = VespaCloud(
    tenant=os.environ["TENANT_NAME"],
    application=vespa_app_name,
    key_content=read_secret() if read_secret() else None,
    key_location=api_key_path,
    application_package=vespa_application_package,
)

Now deploy the app to Vespa Cloud dev zone.

The first deployment typically takes 2 minutes until the endpoint is up.

[64]:
from vespa.application import Vespa

app: Vespa = vespa_cloud.deploy()
Deployment started in run 3 of dev-aws-us-east-1c for samples.colbertlong. This may take a few minutes the first time.
INFO    [19:49:37]  Deploying platform version 8.324.16 and application dev build 3 for dev-aws-us-east-1c of default ...
INFO    [19:49:37]  Using CA signed certificate version 0
INFO    [19:49:46]  Using 1 nodes in container cluster 'colbertlong_container'
INFO    [19:49:51]  Session 2737 for tenant 'samples' prepared and activated.
INFO    [19:49:52]  ######## Details for all nodes ########
INFO    [19:49:52]  h88976a.dev.aws-us-east-1c.vespa-external.aws.oath.cloud: expected to be UP
INFO    [19:49:52]  --- platform vespa/cloud-tenant-rhel8:8.324.16
INFO    [19:49:52]  --- logserver-container on port 4080 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- metricsproxy-container on port 19092 has config generation 2737, wanted is 2737
INFO    [19:49:52]  h88976b.dev.aws-us-east-1c.vespa-external.aws.oath.cloud: expected to be UP
INFO    [19:49:52]  --- platform vespa/cloud-tenant-rhel8:8.324.16
INFO    [19:49:52]  --- container-clustercontroller on port 19050 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- metricsproxy-container on port 19092 has config generation 2737, wanted is 2737
INFO    [19:49:52]  h90246b.dev.aws-us-east-1c.vespa-external.aws.oath.cloud: expected to be UP
INFO    [19:49:52]  --- platform vespa/cloud-tenant-rhel8:8.324.16
INFO    [19:49:52]  --- storagenode on port 19102 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- searchnode on port 19107 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- distributor on port 19111 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- metricsproxy-container on port 19092 has config generation 2737, wanted is 2737
INFO    [19:49:52]  h91714a.dev.aws-us-east-1c.vespa-external.aws.oath.cloud: expected to be UP
INFO    [19:49:52]  --- platform vespa/cloud-tenant-rhel8:8.324.16
INFO    [19:49:52]  --- container on port 4080 has config generation 2737, wanted is 2737
INFO    [19:49:52]  --- metricsproxy-container on port 19092 has config generation 2737, wanted is 2737
INFO    [19:49:52]  Found endpoints:
INFO    [19:49:52]  - dev.aws-us-east-1c
INFO    [19:49:52]   |-- https://a40c1bad.ab8eabb6.z.vespa-app.cloud/ (cluster 'colbertlong_container')
INFO    [19:49:52]  Installation succeeded!
Using mTLS (key,cert) Authentication against endpoint https://a40c1bad.ab8eabb6.z.vespa-app.cloud//ApplicationStatus
Application is up!
Finished deployment.

Use Vespa tensor blocks format for mixed tensors (two mapped dimensions with one dense) doc.

[65]:
from vespa.io import VespaResponse

vespa_feed_format = {
    "id": "1",
    "passages": document_passages,
    "colbert": {"blocks": binarize_token_vectors_hex(document_token_vectors)},
}
with app.syncio() as sync:
    response: VespaResponse = sync.feed_data_point(
        data_id=1, fields=vespa_feed_format, schema="doc"
    )

Querying

This example uses brute-force “true” search without a retrieval step using nearestNeighbor or keywords.

[66]:
from vespa.io import VespaQueryResponse
import json

response: VespaQueryResponse = app.query(
    yql="select * from doc where true",
    ranking="default",
    body={
        "presentation.format.tensors": "short-value",
        "input.query(qt)": float_query_token_vectors(query_vectors),
    },
)
assert response.is_successful()
print(json.dumps(response.hits[0], indent=2))
{
  "id": "id:doc:doc::1",
  "relevance": 100.0651626586914,
  "source": "colbertlong_content",
  "fields": {
    "matchfeatures": {
      "max_sim_per_context": {
        "0": 100.0651626586914,
        "1": 62.7861328125,
        "2": 67.44772338867188,
        "3": 60.133323669433594
      }
    },
    "sddocname": "doc",
    "documentid": "id:doc:doc::1",
    "id": "1",
    "passages": [
      "Alan Turing  was an English mathematician, computer scientist, logician, cryptanalyst, philosopher and theoretical biologist.",
      "Born in Maida Vale, London, Turing was raised in southern England. He graduated from King's College, Cambridge, with a degree in mathematics.",
      "After the war, Turing worked at the National Physical Laboratory, where he designed the Automatic Computing Engine, one of the first designs for a stored-program computer.",
      "Turing has an extensive legacy with statues of him and many things named after him, including an annual award for computer science innovations."
    ],
    "colbert": [
      {
        "address": {
          "context": "0",
          "token": "0"
        },
        "values": [
          1,
          120,
          69,
          0,
          33,
          -60,
          -58,
          -95,
          -120,
          32,
          -127,
          67,
          -51,
          68,
          -106,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "1"
        },
        "values": [
          -122,
          60,
          9,
          -128,
          97,
          -60,
          -58,
          -95,
          -80,
          112,
          -127,
          67,
          -99,
          68,
          -106,
          -28
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "2"
        },
        "values": [
          -28,
          -20,
          73,
          -26,
          -15,
          -28,
          -51,
          40,
          -96,
          113,
          4,
          24,
          -99,
          68,
          -47,
          -28
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "3"
        },
        "values": [
          35,
          74,
          73,
          -95,
          73,
          -51,
          85,
          -128,
          -121,
          25,
          -111,
          68,
          74,
          64,
          -113,
          -27
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "4"
        },
        "values": [
          -109,
          -72,
          -114,
          0,
          65,
          -58,
          -57,
          -95,
          40,
          -96,
          -112,
          67,
          -97,
          43,
          -42,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "5"
        },
        "values": [
          -111,
          56,
          -116,
          0,
          97,
          -58,
          -57,
          -83,
          40,
          -96,
          -127,
          67,
          -33,
          43,
          -42,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "6"
        },
        "values": [
          22,
          57,
          -63,
          96,
          0,
          -60,
          108,
          37,
          16,
          106,
          -55,
          115,
          -117,
          -56,
          -28,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "7"
        },
        "values": [
          -106,
          -72,
          94,
          30,
          32,
          -60,
          -60,
          -51,
          24,
          -56,
          -47,
          -63,
          -8,
          -53,
          -103,
          125
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "9"
        },
        "values": [
          -126,
          105,
          3,
          -103,
          32,
          70,
          103,
          -23,
          88,
          -55,
          -61,
          71,
          -101,
          -106,
          -8,
          -68
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "10"
        },
        "values": [
          18,
          24,
          -106,
          30,
          36,
          -58,
          -28,
          105,
          57,
          -120,
          -128,
          -61,
          -75,
          -53,
          -100,
          -11
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "12"
        },
        "values": [
          22,
          49,
          -38,
          9,
          36,
          -42,
          -25,
          73,
          25,
          -56,
          -45,
          -59,
          -102,
          -2,
          -65,
          125
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "13"
        },
        "values": [
          -111,
          25,
          -50,
          16,
          64,
          -42,
          -28,
          109,
          48,
          -56,
          -112,
          -53,
          -3,
          -119,
          -112,
          -11
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "15"
        },
        "values": [
          55,
          41,
          -62,
          33,
          -91,
          70,
          99,
          32,
          72,
          10,
          -41,
          70,
          -119,
          -78,
          -73,
          -11
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "16"
        },
        "values": [
          3,
          53,
          -118,
          20,
          36,
          -58,
          79,
          1,
          9,
          -120,
          -41,
          69,
          -36,
          -85,
          -111,
          117
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "17"
        },
        "values": [
          23,
          24,
          -42,
          20,
          40,
          -42,
          -26,
          33,
          57,
          -120,
          -112,
          -59,
          -3,
          -24,
          -108,
          -11
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "19"
        },
        "values": [
          -110,
          53,
          -106,
          28,
          32,
          -42,
          -58,
          77,
          61,
          -56,
          -44,
          -15,
          -68,
          -5,
          -110,
          -11
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "20"
        },
        "values": [
          -109,
          56,
          -114,
          0,
          97,
          -58,
          -57,
          -91,
          40,
          -96,
          -128,
          -61,
          -99,
          -21,
          -44,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "21"
        },
        "values": [
          18,
          57,
          -50,
          30,
          36,
          86,
          -60,
          69,
          9,
          -56,
          -48,
          -63,
          -75,
          -22,
          -98,
          117
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "22"
        },
        "values": [
          22,
          -71,
          -98,
          26,
          32,
          -42,
          -50,
          104,
          56,
          64,
          -46,
          -53,
          -4,
          -8,
          -104,
          -12
        ]
      },
      {
        "address": {
          "context": "0",
          "token": "24"
        },
        "values": [
          7,
          120,
          -58,
          2,
          37,
          -58,
          -58,
          33,
          -104,
          34,
          -127,
          67,
          -115,
          32,
          -106,
          -12
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "0"
        },
        "values": [
          5,
          106,
          71,
          -128,
          100,
          -28,
          -34,
          -95,
          -31,
          36,
          -35,
          71,
          -59,
          -28,
          -41,
          -60
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "1"
        },
        "values": [
          7,
          106,
          73,
          -95,
          73,
          -28,
          94,
          -64,
          -105,
          25,
          17,
          4,
          74,
          64,
          -113,
          -27
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "2"
        },
        "values": [
          5,
          74,
          -110,
          2,
          64,
          -28,
          -12,
          -32,
          -28,
          36,
          -35,
          96,
          -49,
          -73,
          94,
          -44
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "3"
        },
        "values": [
          5,
          10,
          22,
          0,
          101,
          100,
          -82,
          -23,
          -25,
          103,
          -35,
          -29,
          -127,
          -91,
          -76,
          85
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "4"
        },
        "values": [
          -49,
          90,
          2,
          40,
          -81,
          -47,
          -78,
          99,
          26,
          66,
          -65,
          101,
          -119,
          -15,
          -68,
          -10
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "5"
        },
        "values": [
          -121,
          89,
          2,
          11,
          -86,
          -41,
          58,
          -5,
          3,
          114,
          23,
          117,
          -75,
          45,
          -80,
          100
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "6"
        },
        "values": [
          7,
          15,
          -59,
          106,
          -89,
          -118,
          122,
          113,
          25,
          74,
          93,
          -9,
          -51,
          -56,
          68,
          -58
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "8"
        },
        "values": [
          66,
          11,
          -121,
          1,
          -128,
          -56,
          34,
          100,
          1,
          51,
          -3,
          115,
          -119,
          -120,
          52,
          -44
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "10"
        },
        "values": [
          99,
          106,
          73,
          -95,
          73,
          -31,
          -33,
          -64,
          -121,
          9,
          -111,
          6,
          72,
          66,
          -81,
          -27
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "11"
        },
        "values": [
          69,
          74,
          6,
          -128,
          96,
          -28,
          -2,
          -31,
          -32,
          36,
          -35,
          -64,
          -59,
          -73,
          87,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "12"
        },
        "values": [
          69,
          78,
          -110,
          2,
          96,
          -4,
          -18,
          -28,
          -31,
          36,
          -36,
          -31,
          -51,
          -79,
          95,
          -44
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "13"
        },
        "values": [
          5,
          10,
          22,
          0,
          97,
          -26,
          -82,
          -23,
          -25,
          103,
          -35,
          -31,
          -127,
          -89,
          -74,
          85
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "14"
        },
        "values": [
          -123,
          30,
          76,
          10,
          68,
          -62,
          -8,
          49,
          1,
          107,
          -35,
          51,
          -35,
          -85,
          -32,
          -42
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "15"
        },
        "values": [
          6,
          11,
          64,
          33,
          16,
          -62,
          -26,
          97,
          0,
          107,
          -35,
          -29,
          -123,
          -119,
          -92,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "17"
        },
        "values": [
          7,
          108,
          79,
          -80,
          36,
          -28,
          -34,
          -127,
          -125,
          48,
          -59,
          6,
          72,
          68,
          -97,
          -59
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "18"
        },
        "values": [
          71,
          74,
          6,
          0,
          100,
          -56,
          -26,
          -87,
          64,
          32,
          -39,
          -127,
          61,
          -6,
          85,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "19"
        },
        "values": [
          69,
          74,
          6,
          0,
          100,
          -22,
          -18,
          -87,
          -27,
          96,
          -35,
          -128,
          -103,
          -79,
          84,
          85
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "20"
        },
        "values": [
          -121,
          104,
          82,
          -62,
          1,
          -62,
          -92,
          11,
          81,
          48,
          -35,
          107,
          -119,
          -52,
          -38,
          -108
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "22"
        },
        "values": [
          71,
          74,
          2,
          0,
          101,
          -64,
          -18,
          -87,
          81,
          32,
          -35,
          -125,
          29,
          -4,
          84,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "23"
        },
        "values": [
          71,
          74,
          18,
          9,
          69,
          74,
          -28,
          -93,
          64,
          32,
          -7,
          -125,
          -99,
          -4,
          84,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "25"
        },
        "values": [
          3,
          45,
          82,
          -63,
          5,
          -64,
          44,
          -93,
          1,
          32,
          -3,
          -61,
          9,
          -54,
          64,
          -42
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "27"
        },
        "values": [
          69,
          74,
          38,
          0,
          100,
          -62,
          -26,
          -87,
          98,
          32,
          -39,
          -128,
          -71,
          -2,
          87,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "28"
        },
        "values": [
          69,
          74,
          6,
          -128,
          100,
          -28,
          -18,
          -95,
          -32,
          32,
          -35,
          -62,
          85,
          -28,
          87,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "29"
        },
        "values": [
          71,
          104,
          38,
          8,
          100,
          -58,
          -28,
          -95,
          100,
          40,
          -7,
          -127,
          -65,
          -18,
          85,
          94
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "30"
        },
        "values": [
          69,
          10,
          38,
          0,
          100,
          -58,
          -90,
          -87,
          72,
          32,
          -39,
          -125,
          -111,
          -18,
          117,
          84
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "31"
        },
        "values": [
          23,
          40,
          86,
          -126,
          32,
          -64,
          108,
          -55,
          8,
          64,
          -7,
          -63,
          -111,
          -118,
          -69,
          116
        ]
      },
      {
        "address": {
          "context": "1",
          "token": "33"
        },
        "values": [
          5,
          106,
          87,
          0,
          100,
          -28,
          -34,
          -95,
          -62,
          34,
          -35,
          67,
          69,
          -28,
          -105,
          -60
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "0"
        },
        "values": [
          -111,
          122,
          71,
          -128,
          36,
          -58,
          -10,
          1,
          -128,
          58,
          -128,
          65,
          9,
          65,
          -50,
          -4
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "1"
        },
        "values": [
          34,
          106,
          73,
          -92,
          65,
          -60,
          -9,
          -128,
          -121,
          24,
          1,
          0,
          72,
          66,
          -113,
          -28
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "2"
        },
        "values": [
          -39,
          -17,
          5,
          0,
          102,
          -42,
          -80,
          62,
          -126,
          41,
          -112,
          64,
          17,
          60,
          -18,
          -102
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "3"
        },
        "values": [
          57,
          91,
          -63,
          -64,
          36,
          -58,
          -106,
          32,
          -62,
          56,
          -111,
          80,
          9,
          64,
          102,
          -50
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "4"
        },
        "values": [
          -71,
          91,
          -63,
          -64,
          38,
          -42,
          26,
          40,
          66,
          56,
          -111,
          96,
          9,
          64,
          98,
          -113
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "6"
        },
        "values": [
          99,
          106,
          73,
          -92,
          73,
          -55,
          -43,
          -128,
          -121,
          25,
          -111,
          0,
          72,
          66,
          -81,
          -27
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "7"
        },
        "values": [
          -24,
          126,
          -42,
          3,
          40,
          -122,
          -90,
          0,
          40,
          -6,
          -31,
          8,
          57,
          -125,
          124,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "8"
        },
        "values": [
          -119,
          90,
          -10,
          2,
          37,
          -50,
          -89,
          41,
          -119,
          90,
          -47,
          0,
          57,
          -111,
          84,
          -44
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "9"
        },
        "values": [
          33,
          90,
          -42,
          0,
          36,
          -122,
          -89,
          43,
          -120,
          90,
          -47,
          0,
          57,
          -127,
          84,
          -44
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "10"
        },
        "values": [
          13,
          90,
          115,
          6,
          5,
          -98,
          102,
          41,
          -128,
          58,
          -48,
          85,
          41,
          -125,
          112,
          -4
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "11"
        },
        "values": [
          17,
          91,
          55,
          15,
          33,
          -108,
          100,
          11,
          8,
          25,
          -48,
          -41,
          -119,
          -63,
          -10,
          52
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "12"
        },
        "values": [
          -126,
          91,
          -5,
          10,
          37,
          -106,
          -18,
          15,
          -128,
          -38,
          -12,
          -59,
          57,
          3,
          -39,
          85
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "14"
        },
        "values": [
          9,
          90,
          118,
          0,
          36,
          -114,
          -89,
          43,
          -53,
          90,
          -63,
          0,
          -71,
          -111,
          84,
          84
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "15"
        },
        "values": [
          33,
          108,
          -49,
          -128,
          36,
          -60,
          -26,
          -127,
          -127,
          56,
          -127,
          0,
          9,
          66,
          -34,
          -28
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "16"
        },
        "values": [
          -77,
          94,
          -105,
          10,
          -88,
          -106,
          -89,
          65,
          8,
          72,
          -128,
          77,
          -99,
          -13,
          85,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "17"
        },
        "values": [
          -109,
          122,
          -33,
          10,
          32,
          -122,
          -89,
          9,
          72,
          10,
          -64,
          -59,
          -103,
          -93,
          92,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "18"
        },
        "values": [
          26,
          -16,
          65,
          81,
          52,
          -60,
          53,
          -71,
          20,
          43,
          88,
          86,
          -111,
          96,
          -6,
          -66
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "19"
        },
        "values": [
          -126,
          105,
          3,
          -103,
          32,
          -44,
          109,
          73,
          8,
          -119,
          -95,
          70,
          88,
          67,
          -20,
          44
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "20"
        },
        "values": [
          -128,
          -3,
          25,
          9,
          50,
          81,
          -27,
          -17,
          -64,
          -69,
          -45,
          70,
          -79,
          -88,
          95,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "22"
        },
        "values": [
          -109,
          120,
          -42,
          2,
          32,
          -122,
          -90,
          9,
          8,
          -118,
          -64,
          -63,
          -99,
          -93,
          84,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "23"
        },
        "values": [
          -109,
          120,
          -41,
          10,
          32,
          -106,
          -89,
          9,
          72,
          10,
          -64,
          -63,
          -103,
          -93,
          84,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "24"
        },
        "values": [
          -109,
          88,
          -41,
          8,
          32,
          -122,
          -89,
          9,
          72,
          10,
          -64,
          -128,
          -103,
          -93,
          92,
          -42
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "25"
        },
        "values": [
          -109,
          76,
          86,
          12,
          26,
          -59,
          103,
          11,
          2,
          11,
          -44,
          -43,
          -99,
          -61,
          -55,
          -82
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "26"
        },
        "values": [
          -77,
          74,
          23,
          42,
          -87,
          -108,
          -89,
          67,
          9,
          9,
          -96,
          13,
          -99,
          -13,
          -51,
          -34
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "27"
        },
        "values": [
          -125,
          110,
          87,
          10,
          32,
          -108,
          39,
          73,
          72,
          10,
          -64,
          69,
          -103,
          99,
          84,
          -98
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "28"
        },
        "values": [
          -126,
          106,
          -109,
          24,
          32,
          -60,
          39,
          73,
          72,
          10,
          -64,
          4,
          -120,
          99,
          86,
          -114
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "29"
        },
        "values": [
          -119,
          98,
          -69,
          -115,
          -92,
          -41,
          125,
          65,
          -24,
          40,
          17,
          17,
          -56,
          112,
          -85,
          -116
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "31"
        },
        "values": [
          9,
          96,
          54,
          -104,
          -92,
          -43,
          109,
          -23,
          9,
          10,
          -15,
          45,
          -123,
          49,
          -13,
          -18
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "32"
        },
        "values": [
          -126,
          105,
          3,
          -103,
          48,
          -58,
          103,
          -23,
          24,
          -118,
          -31,
          70,
          -69,
          83,
          104,
          -116
        ]
      },
      {
        "address": {
          "context": "2",
          "token": "34"
        },
        "values": [
          3,
          107,
          87,
          2,
          36,
          -60,
          -74,
          1,
          72,
          42,
          -111,
          69,
          13,
          2,
          -42,
          -34
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "0"
        },
        "values": [
          36,
          107,
          79,
          20,
          37,
          -60,
          6,
          9,
          -15,
          -14,
          1,
          3,
          -35,
          88,
          -42,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "1"
        },
        "values": [
          38,
          106,
          73,
          -92,
          1,
          -59,
          87,
          -127,
          -105,
          25,
          17,
          0,
          72,
          72,
          -114,
          -28
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "2"
        },
        "values": [
          103,
          106,
          73,
          -95,
          75,
          -55,
          85,
          -64,
          -121,
          25,
          17,
          0,
          74,
          74,
          -81,
          -27
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "3"
        },
        "values": [
          37,
          108,
          -82,
          98,
          97,
          -58,
          38,
          91,
          65,
          -47,
          67,
          34,
          -3,
          90,
          86,
          -28
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "4"
        },
        "values": [
          6,
          108,
          -113,
          22,
          -32,
          -28,
          38,
          25,
          97,
          65,
          82,
          34,
          -103,
          90,
          86,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "5"
        },
        "values": [
          22,
          108,
          -91,
          70,
          96,
          -92,
          38,
          9,
          -31,
          9,
          83,
          58,
          -71,
          -6,
          100,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "6"
        },
        "values": [
          18,
          108,
          -89,
          6,
          102,
          36,
          34,
          8,
          103,
          -119,
          80,
          -78,
          -6,
          -38,
          86,
          -84
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "7"
        },
        "values": [
          -125,
          105,
          -82,
          6,
          -31,
          -124,
          38,
          83,
          81,
          65,
          3,
          34,
          -71,
          88,
          86,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "8"
        },
        "values": [
          -110,
          41,
          94,
          23,
          1,
          -67,
          -95,
          -45,
          81,
          80,
          113,
          -25,
          -71,
          -48,
          82,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "9"
        },
        "values": [
          -79,
          109,
          6,
          22,
          69,
          -108,
          38,
          89,
          80,
          -14,
          19,
          11,
          -87,
          88,
          -10,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "10"
        },
        "values": [
          36,
          125,
          27,
          -108,
          36,
          -60,
          6,
          65,
          -127,
          16,
          -127,
          0,
          -55,
          78,
          -66,
          -27
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "11"
        },
        "values": [
          -109,
          105,
          -114,
          6,
          101,
          -124,
          38,
          25,
          113,
          -63,
          2,
          35,
          -103,
          88,
          86,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "12"
        },
        "values": [
          21,
          121,
          -114,
          102,
          -90,
          -92,
          40,
          91,
          83,
          -117,
          2,
          66,
          -71,
          90,
          84,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "13"
        },
        "values": [
          -112,
          -8,
          -82,
          38,
          -126,
          -123,
          98,
          11,
          83,
          -55,
          -126,
          -58,
          -71,
          -44,
          20,
          -36
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "14"
        },
        "values": [
          -112,
          45,
          70,
          39,
          -57,
          -68,
          43,
          15,
          112,
          120,
          3,
          66,
          -67,
          -40,
          114,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "15"
        },
        "values": [
          -71,
          -91,
          4,
          4,
          70,
          -74,
          -95,
          31,
          81,
          -37,
          -106,
          79,
          -96,
          -4,
          -9,
          -72
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "16"
        },
        "values": [
          32,
          61,
          11,
          -108,
          36,
          -59,
          6,
          -128,
          -127,
          17,
          -127,
          0,
          -55,
          76,
          -66,
          -27
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "18"
        },
        "values": [
          -105,
          104,
          46,
          6,
          -32,
          -124,
          38,
          59,
          115,
          -7,
          19,
          34,
          -71,
          88,
          84,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "19"
        },
        "values": [
          -127,
          105,
          47,
          20,
          101,
          -124,
          38,
          57,
          64,
          -16,
          18,
          35,
          -99,
          88,
          84,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "20"
        },
        "values": [
          12,
          105,
          115,
          92,
          -11,
          -12,
          46,
          59,
          64,
          -24,
          19,
          47,
          -71,
          104,
          84,
          -4
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "21"
        },
        "values": [
          -96,
          105,
          97,
          54,
          -27,
          -92,
          -90,
          59,
          64,
          -8,
          19,
          103,
          -67,
          104,
          85,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "22"
        },
        "values": [
          -127,
          43,
          110,
          16,
          101,
          -124,
          -90,
          41,
          64,
          -22,
          19,
          -117,
          -99,
          72,
          84,
          -12
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "23"
        },
        "values": [
          50,
          105,
          19,
          -103,
          -96,
          70,
          39,
          -55,
          88,
          75,
          -93,
          70,
          -103,
          70,
          -8,
          -68
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "24"
        },
        "values": [
          3,
          59,
          -1,
          29,
          -92,
          -122,
          -84,
          73,
          17,
          72,
          -94,
          -117,
          -107,
          -54,
          -76,
          116
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "25"
        },
        "values": [
          -125,
          11,
          -41,
          30,
          -89,
          -92,
          -90,
          11,
          81,
          11,
          2,
          -86,
          -3,
          -54,
          -108,
          84
        ]
      },
      {
        "address": {
          "context": "3",
          "token": "27"
        },
        "values": [
          7,
          41,
          91,
          20,
          37,
          -60,
          46,
          67,
          81,
          42,
          25,
          67,
          -39,
          72,
          -76,
          -12
        ]
      }
    ]
  }
}

As can be seen from the matchfeatures, the first context (index 0) scored the highest and this is the score that is used to score the entire document.

[ ]:
vespa_cloud.delete()