Skip to content

Resolvers

Resolvers are the mechanism Aspected uses to convert structured data into numeric embedding vectors. When you create an index, you define a schema — a list of aspects — and each aspect is powered by a resolver.

Every aspect has five properties:

Property Description
name A unique name for this aspect within the index.
type The resolver type to use (enum, text, number, datetime, dict, or raw).
path A JSONPath expression that extracts the value from a training document.
settings A resolver-specific settings object (see the sections below).
multiplier (≥0.2.0) Floating point value that scales the output vector of resolved inputs. Defaults to 1.

During training, each document is passed through every aspect's resolver. The resolver uses the path to extract a value from the document, converts it to a fixed-length float vector, and the resulting vectors are concatenated to form the full composite vector stored in the index.

During search, you supply a query containing values for any subset of aspects. Dimensions for aspects you omit are left undefined (sparse), so only the aspects you specify contribute to the similarity calculation.

Available Resolvers

Resolver Input type Description
Enum ≥0.1.0 string Maps a categorical value to a radial embedding.
Text ≥0.1.0 string Generates a semantic embedding using a GGUF model.
Number ≥0.1.0 number Maps a numeric value within a range to a radial embedding.
DateTime ≥0.1.0 string Maps a date/time string to a variable dimension embedding.
Raw ≥0.1.0 array of numbers Pass-through for pre-computed embedding vectors.
Dictionary ≥0.3.0 string Uses a key-value map to generate embeddings from input keys.

JSONPath Expressions

The path property on each aspect uses a JSONPath expression to extract a value from a training document. This allows you to use nested or complex document structures.

Examples

Given the following training document:

{
  "id": "item-1",
  "doc": {
    "name": "Widget",
    "category": "tools",
    "details": {
      "description": "A handy widget for everyday use"
    }
  }
}
Path Extracted value
$.category "tools"
$.details.description "A handy widget for everyday use"
$.name "Widget"

Combining Resolvers

An index can use multiple aspects with different resolver types. For example, you might combine an enum aspect for categorical filtering, a text aspect for semantic search, and a number aspect for price similarity:

{
  "idSize": 36,
  "aspects": [
    {
      "name": "category",
      "type": "enum",
      "path": "$.category",
      "settings": {
        "values": [
          "electronics",
          "clothing",
          "food",
          "tools"
        ]
      }
    },
    {
      "name": "description",
      "type": "text",
      "path": "$.description",
      "settings": {
        "model": "nomic-embed-text-v1.5.f16.gguf"
      }
    },
    {
      "name": "price",
      "type": "number",
      "path": "$.price",
      "settings": {
        "min": 0.0,
        "max": 500.0
      }
    }
  ]
}

When searching, you can query with any combination of aspects:

{
  "k": 5,
  "query": {
    "category": "electronics"
  }
}

This searches only on the category aspect — all other dimensions are ignored.

{
  "k": 5,
  "query": {
    "description": "a durable outdoor tool"
  }
}

This searches only on the description aspect — the enum and number dimensions are ignored.

{
  "k": 5,
  "query": {
    "category": "tools",
    "description": "a durable outdoor tool"
  }
}

This searches on both aspects simultaneously.

Inspecting Resolvers

You can also add "withExplanation": true to the search call to receive a basic metric for search aspects' influence on the result, with the response.

For example, the query:

{
  "k": 5,
  "query": {
    "category": "tools",
    "description": "a durable outdoor tool"
  },
  "withExplanation": true
}

Might receive a response that looks something like:

[
  {
    "id": "0000",
    "distance": 0.267330492390,
    "explanation": [
      { "aspectName": "category", "value": "tools", "distance": 0 },
      { "aspectName": "description", "value": "sturdy steel rake", "distance": 0.412 },
      { "aspectName": "price", "value": "67.99" }
    ]
  },
  {
    "id": "0001",
    "distance": 0.45537900924683,
    "explanation": [
      { "aspectName": "category", "value": "tools", "distance": 0 },
      { "aspectName": "description", "value": "small hex-head screwdriver", "distance": 0.9 },
      { "aspectName": "price", "value": "12.99" }
    ]
  }
]

Note that price has no distance, this is because it was not featured in the search query (this can also occur if present in query but an extremely tiny weight is applied to the aspect).

Search explanation can be a useful tool for fine-tuning search weights, in the above case, you might greatly increase weighting for the description, which would bias the search toward 0000 as it has the more semantically similar description. You might also add price to the search query (e.g. "price": 80.0) but give it a small weighting. Using the search explanation for feedback, you can repeat the same search with different weight values to develop your search criteria for the greatest effectiveness.

Making the two changes to the search query may result in another result that looks like this:

[
  {
    "id": "0000",
    "distance": 0.5141975260,
    "explanation": [
      { "aspectName": "category", "value": "tools", "distance": 0 },
      { "aspectName": "description", "value": "sturdy steel rake", "distance": 0.612 },
      { "aspectName": "price", "value": "67.99", "distance": 0.16 }
    ]
  },
  {
    "id": "0001",
    "distance": 1.48683510597,
    "explanation": [
      { "aspectName": "category", "value": "tools", "distance": 0 },
      { "aspectName": "description", "value": "small hex-head screwdriver", "distance": 1.9 },
      { "aspectName": "price", "value": "12.99", "distance": 0.78666 }
    ]
  }
]

With the higher weighting applied to the description, for both results this aspect now has a larger distance, and the overall distance is increased. The important change, however, is that the distance between IDs 0000 and 0001 is now much greater from this search query - in this example this makes little difference as we only have these 2 entries in the example database, but in a larger database this will completely change the search results toward the bias specified.