> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate with missing answers

> Give a rater a partial request and read what comes back: settled outcomes, a refusal, or the open questions that still matter.

[Install Relativities](https://docs.canary.effectiveai.app/relativities/setup.md) before running the synthetic examples.

`rslc.PreparedRater.evaluate` rates one request that leaves inputs out.
It returns the outcomes when the given answers settle them, and a refusal when a given answer breaks a rule.
Otherwise it returns each missing input that still matters, as a gap.

## Evaluate a partial request

Save the shared renters example, a rater from the synthetic carrier Example Mutual:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc examples get renters
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
WROTE renters/rater.rsl
WROTE renters/tables/BaseRate.csv
WROTE renters/tables/BuildingFactor.csv
WROTE renters/tables/DeductibleFactor.csv
```

Load the folder and evaluate a request that holds two answers:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
import json

import rslc

rater = rslc.PreparedRater("renters")


def evaluate(policy):
    return json.loads(rater.evaluate(json.dumps({"Policy": policy})))


print(evaluate({"contents": 30000, "territory": "rural"}))
# {'open': {'gaps': [{'path': 'Policy.insured_now'}, {'path': 'Policy.has_dog'}], 'known': {}}}
```

* `rater.evaluate` takes one request as JSON text and returns JSON text.
* `evaluate` is a helper in ordinary Python. It wraps the answers in the root record `Policy` and parses the result.
* The result is `open`: the premium still depends on `insured_now` and `has_dog`.

The rater declares seven inputs. The two gaps are the inputs that still change its result:

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
inputs {
    insured_now: Bool [ask: "Do you have a renters policy now?", group: "Insurance", gives: "declarations_page"],
    contents: Num {precision: int} [ask: "What are your belongings worth?", help: "Count furniture, clothing and electronics.", group: "Home", found_on: "declarations_page"]
        where self in [10000, 100000],
    territory: Territory [ask: "Where is the home?", group: "Home"],
    construction: Construction [ask: "How is the building built?", group: "Home"],
    has_dog: Bool [ask: "Do you have a dog?", group: "Household"],
    dog_has_bitten: Bool when self.has_dog [ask: "Has the dog bitten anyone?", group: "Household"]
        where not self [code: "DOG-BITE", message: "The program declines a dog with a bite history.", cite: manual:p5],
    deductible: Deductible [choice, api_default: "500", ask: "Which deductible do you want?", group: "Coverage"]
},
```

[Example raters](https://docs.canary.effectiveai.app/rsl/reference/examples.md#renters) shows the whole rater and its tables.

## Read the open questions

Evaluate an empty request:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
for gap in evaluate({})["open"]["gaps"]:
    print(gap)
# {'path': 'Policy.insured_now'}
# {'path': 'Policy.contents'}
# {'choices': ['metro', 'suburban', 'rural'], 'more': True, 'path': 'Policy.territory'}
# {'choices': ['frame', 'masonry', 'fire_resistive'], 'more': True, 'path': 'Policy.construction'}
# {'path': 'Policy.has_dog'}
```

* `path` names the input in the request. The gaps arrive in the order the rater needs them.
* `choices` lists the values that the rate tables file for the input.
* `more` is `true` when the table also has an all-other row, so a value outside `choices` is valid too.

Two inputs stay off the list:

* `deductible` is a choice with a default. A request that leaves it out buys the \$500 deductible.
* `dog_has_bitten` is a follow-up input. It becomes a gap only when `has_dog` is `true`.

## See an answer narrow the next question

The building table files a factor for each territory and construction, and 1.20 for all other pairs:

```csv theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
territory,construction,factor
metro,frame,1.30
metro,masonry,1.15
metro,fire_resistive,1.00
suburban,frame,1.10
suburban,masonry,1.00
rural,frame,1.20
rural,masonry,1.20
rural,fire_resistive,1.20
```

Answer `territory` and read the gap for `construction`:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
for territory in ["metro", "suburban", "rural"]:
    gaps = evaluate({"territory": territory})["open"]["gaps"]
    print(territory, [gap for gap in gaps if gap["path"] == "Policy.construction"])
# metro [{'choices': ['frame', 'masonry', 'fire_resistive'], 'path': 'Policy.construction'}]
# suburban [{'choices': ['frame', 'masonry'], 'more': True, 'path': 'Policy.construction'}]
# rural []
```

* `metro` has a row for each construction, so `choices` is the whole list.
* `suburban` has two rows. A fire-resistive building takes the all-other factor, so `more` is `true`.
* `rural` has one factor for every construction, so `construction` stops being a gap.

## Read a settled result

Give the four answers that a rural policy needs:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
answers = {"insured_now": False, "contents": 30000, "territory": "rural", "has_dog": False}
print(evaluate(answers))
# {'settled': {'ok': True, 'outputs': {'Policy': {'premium': 216}}}}
```

The annual premium is \$216. The request still leaves `construction` out.
Each value of `construction` gives the same premium, so the result is final.

An `open` result also reports each outcome that is already settled, under `known`:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
print(evaluate({**answers, "has_dog": True}))
# {'open': {'gaps': [{'path': 'Policy.dog_has_bitten'}], 'known': {'premium': 241}}}
```

The follow-up input `dog_has_bitten` now applies, and a business rule reads it.
The premium is \$241 for each answer that the rule accepts.

## Read a refusal

A given answer that breaks a business rule settles the request as a refusal:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
result = evaluate({"has_dog": True, "dog_has_bitten": True})
print(result["settled"]["ok"])
# False
for violation in result["settled"]["refusal"]["violations"]:
    print(violation["code"], violation["path"], violation["message"])
# DOG-BITE Policy.dog_has_bitten The program declines a dog with a bite history.
```

The refusal is final. An answer to an input that the request leaves out keeps it the same.
[Refusals](https://docs.canary.effectiveai.app/rsl/reference/refusals.md) lists each field of a violation.

## Correct an invalid answer

A given value outside its type or range returns `invalid`:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
result = evaluate({"contents": 5000})
print(result["invalid"]["refusal"]["violations"][0]["message"])
# contents is below declared minimum 10000
```

Correct the value and evaluate again.

To mark an input as unanswered, leave its key out of the request.
A `null` for a required input counts as a given value, and the result is `invalid`:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
print(evaluate({"insured_now": None})["invalid"]["refusal"]["violations"][0]["message"])
# missing required input insured_now
```

## Evaluate a book of submissions

To evaluate each submission of a book, pass `allow_missing=True` to `Program.rate`.
[Rate a book with a program](https://docs.canary.effectiveai.app/relativities/how-to/rate-a-book-with-a-program.md) shows the `open` status and the `gaps` column.

## Related

* [Missing answers](https://docs.canary.effectiveai.app/rsl/explanation/missing-answers.md) explains why a rater answers a partial request.
* [Results](https://docs.canary.effectiveai.app/rsl/reference/results.md) lists each field of the three results.
* [Plan the next question](https://docs.canary.effectiveai.app/rsl/how-to/plan-the-next-question.md) turns the gaps of several raters into question cards.
* [Ask the questions a rater needs](https://docs.canary.effectiveai.app/rsl/tutorial/ask-questions.md) writes the `ask` and `when` forms.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.