# Smart Rules and Dynamic Parameters

## UniqueQL to Qdrant Filter Documentation

## Introduction

UniqueQL is a specialized query language used for building complex filters to query data within Unique. This documentation provides a guide on using UniqueQL, with an emphasis on enhancing queries through the use of predefined variables and dynamic values. Various examples are included to demonstrate these techniques in practice.

These filters can be applied in smart rules within a Space and also in queries for modules created using the SDK.

For more details, you can refer to the following documentation:

- [Extended Search with UniqueQL on Metadata](https://docs.unique.ai/administrators/space-management/smart-rules/extended-search-with-uniqueql-on-metadata)

### Video 🎥

## Variables and Setup

### SmartRuleVariables

The `SmartRuleVariables` object contains predefined variables that can be used within UniqueQL queries. These variables are divided into two categories: `userMetadata` and `toolParameters`.

- `userMetadata`: This data is derived from the information in Groups and Users.

- `toolParameters`: These are derived from the tool selection made during the module choice process. The parameters are determined by the model based on the chosen module and are then passed as arguments in the `toolParameter` parameter.

```javascript
const SmartRuleVariables = {
  userMetadata: {
    location: 'NY',
    favCheese: 'Cheddar',
    IdoExist: 'funny bunny',
  },
  toolParameters: {
    location: 'Switzerland',
    favCheese: 'Gruyere',
    numberOfCows: 100,
    someBoolean: true,
  },
};
```

## Enriching Queries with Variables

The `enrichSmartRulesWithVariables` function is used to replace placeholders in UniqueQL queries with actual values from `SmartRuleVariables`.

### **Example**: Numbers

**Query:**

```javascript
{
  path: ['cows'],
  operator: Operator.EQUALS,
  value: '<toolParameters.numberOfCows>',
}
```

**Result:**

```javascript
{
    path: ['cows'],
    operator: Operator.EQUALS,
    value: 100,
}
```

**Explanation:**

The placeholder `<toolParameters.numberOfCows>` is replaced with `100`.

* * *

### **Example**: Booleans

**Query:**

```javascript
{
    path: ['hasCows'],
    operator: Operator.EQUALS,
    value: '<toolParameters.someBoolean>',
}
```

**Result:**

```javascript
{
    path: ['hasCows'],
    operator: Operator.EQUALS,
    value: true,
}
```

**Explanation:**

The placeholder `<toolParameters.someBoolean>` is replaced with `true`.

* * *

### **Example**: Time Manipulation

**Future Time:**

**Query:**

```javascript
{
    path: ['ttime'],
    operator: Operator.EQUALS,
    value: '<T+1000>',
}
```

**Result:**

```javascript
{
    path: ['ttime'],
    operator: Operator.EQUALS,
    value: new Date(Date.now() + 1000),
}
```

**Explanation:**

The placeholder `<T+1000>` is replaced with the current time plus 1000 milliseconds.

* * *

### **Example**: Past Time

**Query:**

```javascript
{
    path: ['ttime'],
    operator: Operator.EQUALS,
    value: '<T-1000>',
}
```

**Result:**

```javascript
{
    path: ['ttime'],
    operator: Operator.EQUALS,
    value: new Date(Date.now() - 1000),
}
```

**Explanation:**

The placeholder `<T-1000>` is replaced with the current time minus 1000 milliseconds.

* * *

### **Example**: User Metadata

**Query:**

```javascript
{
    path: ['location'],
    operator: Operator.EQUALS,
    value: '<userMetadata.location>',
}
```

**Result:**

```javascript
{
    path: ['location'],
    operator: Operator.EQUALS,
    value: 'NY',
}
```

**Explanation:**

The placeholder `<userMetadata.location>` is replaced with `NY`.

* * *

### **Example**: Tool Parameters

**Query:**

```javascript
{
    path: ['country'],
    operator: Operator.EQUALS,
    value: '<toolParameters.location>',
}
```

**Result:**

```javascript
{
    path: ['country'],
    operator: Operator.EQUALS,
    value: 'Switzerland',
}
```

**Explanation:**

The placeholder `<toolParameters.location>` is replaced with `Switzerland`.

* * *

### **Example**: IN Operator

**Query:**

```javascript
{
    path: ['places', '*', 'likes'],
    operator: Operator.IN,
    value: ['<toolParameters.location>', '<userMetadata.location>'],
}
```

**Result:**

```javascript
{
    path: ['places', '*', 'likes'],
    operator: Operator.IN,
    value: ['Switzerland', 'NY'],
}
```

**Explanation:**

The placeholders `<toolParameters.location>` and `<userMetadata.location>` are replaced with `Switzerland` and `NY`, respectively.

* * *

### **Example**: Nested AND Operator

**Query:**

```javascript
{
    path: ['places', '*'],
    operator: Operator.NESTED,
    value: {
        and: [
            {
                path: ['likes'],
                operator: Operator.EQUALS,
                value: '<userMetadata.location>',
            },
            {
                path: ['livesIn'],
                operator: Operator.EQUALS,
                value: '<userMetadata.location>',
            },
        ],
    },
}
```

**Result:**

```javascript
{
    path: ['places', '*'],
    operator: Operator.NESTED,
    value: {
        and: [
            {
                path: ['likes'],
                operator: Operator.EQUALS,
                value: 'NY',
            },
            {
                path: ['livesIn'],
                operator: Operator.EQUALS,
                value: 'NY',
            },
        ],
    },
}
```

**Explanation:**

The placeholders `<userMetadata.location>` are replaced with `NY` in both conditions.

* * *

### **Example**: Fallback Mechanisms

**Fallback to Existing:**

**Query:**

```javascript
{
  path: ['data'],
  operator: Operator.EQUALS,
  value: '<userMetadata.IdoNotExist>||<userMetadata.IdoExist>',
}
```

**Result:**

```javascript
{
  path: ['data'],
  operator: Operator.EQUALS,
  value: 'funny bunny',
}
```

**Explanation:**

The placeholder `<userMetadata.IdoNotExist>` does not exist, so it falls back to `<userMetadata.IdoExist>`, which is `funny bunny`.

* * *

**Fallback to Static Value:**

**Query:**

```javascript
{
  path: ['data'],
  operator: Operator.EQUALS,
  value: '<userMetadata.IdoNotExist>||<toolParameters.IdoNotExist>||SomeValue',
}
```

**Result:**

```javascript
{
  path: ['data'],
  operator: Operator.EQUALS,
  value: 'SomeValue',
}
```

**Explanation:**

None of the placeholders exist, so it falls back to the static value `SomeValue`.

## How to add metadata

Refer to [Multitenant Region URLs](https://docs.unique.ai/it-operators/installing-and-upgrading-unique/multitenant-region-urls) to find the correct base URL for your deployment.

### Content Metadata

Content metadata can be added/updated using the ingestion API. An example cURL for updating metadata of an existing file looks as follows.

```bash
curl --location 'http://gateway.<baseUrl>/ingestion/graphql' \
--header 'Content-Type: <MIME_TYPE>' \
--header 'Authorization: <your-access-token>' \
--data '{"query":"mutation ContentUpsert($input: ContentCreateInput!, $scopeId: String, $sourceOwnerType: String, $sourceName: String, $storeInternally: Boolean, $text: String, $sourceKind: String)\n{\n  contentUpsert(\n    input: $input\n    scopeId: $scopeId\n    sourceOwnerType: $sourceOwnerType\n    sourceName: $sourceName\n    storeInternally: $storeInternally\n    text: $text\n    sourceKind: $sourceKind\n  ) {\n     id\n     title\n     metadata\n     key\n     byteSize\n     mimeType\n     ownerType\n     ownerId\n     writeUrl\n     readUrl\n     createdAt\n     internallyStoredAt\n  }\n}\n\n\n\n","variables":{"input":{"title":"BMW_heritage.pdf","key":"BMW_heritage.pdf","mimeType":"application/pdf","ownerType":"SCOPE","metadata":{"location":"GEN","Territory":"Switzerland"}},"scopeId":"<scopeId>","sourceOwnerType":"COMPANY","sourceKind":"UNIQUE_BLOB_STORAGE"}}'
```

See [File Ingestion](https://docs.unique.ai/administrators/knowledge-base-for-admins/file-ingestion) for further details on Ingestion API.

### User/Group Metadata

The metadata of a user or group can be updated by using the cURL call as follows.

```powershell
curl --location 'https://gateway.<baseUrl>/scope-management/graphql' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <yourToken>' \
--data '{"query":"mutation UpdateGroup($updateGroupId: String!, $input: GroupUpdateInput!) {\n  updateGroup(id: $updateGroupId, input: $input) {\n    id\n  }\n}","variables":{"updateGroupId":"<groupId>","input":{"configuration": {"location": "switzerland"}}}}'
```

## Setup your Assistant 🎥

> **NOTE**: While the video shows smart rules setup via Advanced Settings, you will find it more convenient to [Defining Smart Rules through Knowledge Scope Rules](https://docs.unique.ai/administrators/space-management/smart-rules/defining-smart-rules-through-knowledge-scope-rules)

## Use with SDK and Toolkit 🎥

## Conclusion

UniqueQL provides a flexible mechanism to construct complex queries by leveraging dynamic variables and placeholders. By using the `enrichSmartRulesWithVariables` function, you can easily replace placeholders with actual values from predefined variables, enabling dynamic and context-aware query construction. The examples provided in this documentation should help you understand and utilize these techniques effectively.
