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

# Decisions

> Ask yes/no, multiple-choice and scale questions about any text and get calibrated, typed answers back

<Warning>
  **Experimental.** Jev support is new and the `questions` response format is not yet stable. The request and response shapes documented here may change in a future release without a deprecation period.
</Warning>

Jev is a decision model built by Typesafe. Instead of generating free-form text, it evaluates a piece of content against a set of **questions** you define and returns a typed answer for each one, together with a probability distribution over the possible outcomes. That makes it a good fit for classification, moderation, sentiment analysis, grading and any other place where you want a calibrated score rather than prose.

Through Requesty you call Jev with the same Chat Completions, Messages or Responses API you already use for every other model. The only difference is the response format: you pass your questions in `response_format` (or its equivalent) and read the answers back as JSON in the assistant message.

<Note>
  **[Get your API key](https://app.requesty.ai/api-keys)** in the Requesty Console.
</Note>

## Models

| Model                 | Notes                                   |
| --------------------- | --------------------------------------- |
| `typesafe/jev-latest` | Always points at the newest Jev release |

## How it works

A Jev request has two parts:

1. **State**: the content to evaluate. Send it as the text of one or more `user` messages. Several user messages are joined with blank lines.
2. **Questions**: a map of question id to question definition, passed as `{"type": "questions", "questions": {...}}` in the response format field of the API you are using.

The response is a single assistant message whose content is a JSON object with one entry per question id. Every answer carries a `type` field matching the question type.

<Warning>
  Only the following are supported when calling Jev:

  * `user` messages with text content. `system`, `assistant` and `tool` messages, images, files and tool definitions are rejected.
  * Non-streaming requests. `stream: true` returns a `400`.
  * A `questions` response format. `json_object`, `json_schema` and plain text are not supported by this model.
</Warning>

## Question types

Jev supports three question types. You can mix them freely in one request; each question is answered independently.

### `noul`: yes / no

A `noul` question asks whether a statement about the content is true. The answer is a probability between `0.0` and `1.0`.

```json theme={"dark"}
{
  "positive": {
    "type": "noul",
    "instructions": "The review is positive."
  }
}
```

Answer:

```json theme={"dark"}
{
  "positive": {
    "type": "noul",
    "noul": 0.98
  }
}
```

### `choice`: pick one option

A `choice` question picks one of several labelled options. `criteria` maps each option key to a description of when it applies. The answer contains the winning key in `choice`, plus `probabilities` for every option and the overall `confidence`.

```json theme={"dark"}
{
  "sentiment": {
    "type": "choice",
    "instructions": "What is the sentiment of the review?",
    "criteria": {
      "positive": "The reviewer liked the book.",
      "negative": "The reviewer disliked the book.",
      "neutral": "The reviewer has no strong opinion."
    }
  }
}
```

Answer:

```json theme={"dark"}
{
  "sentiment": {
    "type": "choice",
    "choice": "positive",
    "confidence": 0.97,
    "probabilities": {
      "positive": 0.97,
      "negative": 0.01,
      "neutral": 0.02
    }
  }
}
```

### `score`: position on an ordered scale

A `score` question places the content on an ordered scale. `criteria` is a list of labels from lowest to highest. The answer is the zero-based index of the chosen label in `score`, with `probabilities` keyed by index, a `legend` mapping indices back to labels, and the overall `confidence`.

```json theme={"dark"}
{
  "rating": {
    "type": "score",
    "instructions": "How much did the reviewer enjoy the book?",
    "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"]
  }
}
```

Answer:

```json theme={"dark"}
{
  "rating": {
    "type": "score",
    "score": 4,
    "confidence": 0.91,
    "legend": {
      "0": "Hated it",
      "1": "Disliked it",
      "2": "Neutral",
      "3": "Liked it",
      "4": "Loved it"
    },
    "probabilities": {
      "0": 0.0,
      "1": 0.0,
      "2": 0.01,
      "3": 0.08,
      "4": 0.91
    }
  }
}
```

## Examples

The examples below ask all three question types about the same book review. Swap in your own content and questions.

### Chat Completions API

Pass the questions in `response_format`.

<Tabs>
  <Tab title="Python (OpenAI SDK)">
    ```python theme={"dark"}
    import json
    from openai import OpenAI

    client = OpenAI(
        api_key="YOUR_REQUESTY_API_KEY",
        base_url="https://router.requesty.ai/v1",
    )

    review = (
        "This book was an absolute delight, I could not put it down "
        "and finished it in one sitting."
    )

    questions = {
        "positive": {
            "type": "noul",
            "instructions": "The review is positive.",
        },
        "sentiment": {
            "type": "choice",
            "instructions": "What is the sentiment of the review?",
            "criteria": {
                "positive": "The reviewer liked the book.",
                "negative": "The reviewer disliked the book.",
                "neutral": "The reviewer has no strong opinion.",
            },
        },
        "rating": {
            "type": "score",
            "instructions": "How much did the reviewer enjoy the book?",
            "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
        },
    }

    completion = client.chat.completions.create(
        model="typesafe/jev-latest",
        messages=[{"role": "user", "content": review}],
        response_format={"type": "questions", "questions": questions},
    )

    answers = json.loads(completion.choices[0].message.content)
    print(answers["positive"]["noul"])       # 0.98
    print(answers["sentiment"]["choice"])    # "positive"
    print(answers["rating"]["score"])        # 4
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"dark"}
    import OpenAI from "openai";

    const client = new OpenAI({
      apiKey: "YOUR_REQUESTY_API_KEY",
      baseURL: "https://router.requesty.ai/v1",
    });

    const review =
      "This book was an absolute delight, I could not put it down and finished it in one sitting.";

    const questions = {
      positive: {
        type: "noul",
        instructions: "The review is positive.",
      },
      sentiment: {
        type: "choice",
        instructions: "What is the sentiment of the review?",
        criteria: {
          positive: "The reviewer liked the book.",
          negative: "The reviewer disliked the book.",
          neutral: "The reviewer has no strong opinion.",
        },
      },
      rating: {
        type: "score",
        instructions: "How much did the reviewer enjoy the book?",
        criteria: ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
      },
    };

    const completion = await client.chat.completions.create({
      model: "typesafe/jev-latest",
      messages: [{ role: "user", content: review }],
      // The SDK types do not know about "questions" yet, hence the cast
      response_format: { type: "questions", questions } as any,
    });

    const answers = JSON.parse(completion.choices[0].message.content!);
    console.log(answers.positive.noul);     // 0.98
    console.log(answers.sentiment.choice);  // "positive"
    console.log(answers.rating.score);      // 4
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"dark"}
    curl https://router.requesty.ai/v1/chat/completions \
      -H "Authorization: Bearer YOUR_REQUESTY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "typesafe/jev-latest",
        "messages": [
          {
            "role": "user",
            "content": "This book was an absolute delight, I could not put it down and finished it in one sitting."
          }
        ],
        "response_format": {
          "type": "questions",
          "questions": {
            "positive": {
              "type": "noul",
              "instructions": "The review is positive."
            },
            "sentiment": {
              "type": "choice",
              "instructions": "What is the sentiment of the review?",
              "criteria": {
                "positive": "The reviewer liked the book.",
                "negative": "The reviewer disliked the book.",
                "neutral": "The reviewer has no strong opinion."
              }
            },
            "rating": {
              "type": "score",
              "instructions": "How much did the reviewer enjoy the book?",
              "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"]
            }
          }
        }
      }'
    ```
  </Tab>
</Tabs>

The answers come back as the JSON content of the assistant message:

```json theme={"dark"}
{
  "id": "req_...",
  "object": "chat.completion",
  "model": "typesafe/jev-latest",
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": {
        "role": "assistant",
        "content": "{\"positive\":{\"type\":\"noul\",\"noul\":0.98},\"sentiment\":{\"type\":\"choice\",\"choice\":\"positive\",\"confidence\":0.97,\"probabilities\":{\"positive\":0.97,\"negative\":0.01,\"neutral\":0.02}},\"rating\":{\"type\":\"score\",\"score\":4,\"confidence\":0.91,\"legend\":{\"0\":\"Hated it\",\"1\":\"Disliked it\",\"2\":\"Neutral\",\"3\":\"Liked it\",\"4\":\"Loved it\"},\"probabilities\":{\"0\":0.0,\"1\":0.0,\"2\":0.01,\"3\":0.08,\"4\":0.91}}}"
      }
    }
  ],
  "usage": {
    "prompt_tokens": 448,
    "completion_tokens": 55,
    "total_tokens": 503
  }
}
```

### Messages API

Pass the questions in `output_config.format`.

<Tabs>
  <Tab title="Python (Anthropic SDK)">
    ```python theme={"dark"}
    import json
    from anthropic import Anthropic

    client = Anthropic(
        api_key="YOUR_REQUESTY_API_KEY",
        base_url="https://router.requesty.ai",
    )

    review = (
        "This book was an absolute delight, I could not put it down "
        "and finished it in one sitting."
    )

    questions = {
        "positive": {
            "type": "noul",
            "instructions": "The review is positive.",
        },
        "sentiment": {
            "type": "choice",
            "instructions": "What is the sentiment of the review?",
            "criteria": {
                "positive": "The reviewer liked the book.",
                "negative": "The reviewer disliked the book.",
                "neutral": "The reviewer has no strong opinion.",
            },
        },
        "rating": {
            "type": "score",
            "instructions": "How much did the reviewer enjoy the book?",
            "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
        },
    }

    message = client.messages.create(
        model="typesafe/jev-latest",
        max_tokens=1024,
        messages=[{"role": "user", "content": review}],
        output_config={
            "format": {"type": "questions", "questions": questions},
        },
    )

    answers = json.loads(message.content[0].text)
    print(answers["sentiment"]["choice"])  # "positive"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"dark"}
    import Anthropic from "@anthropic-ai/sdk";

    const client = new Anthropic({
      apiKey: "YOUR_REQUESTY_API_KEY",
      baseURL: "https://router.requesty.ai",
    });

    const review =
      "This book was an absolute delight, I could not put it down and finished it in one sitting.";

    const questions = {
      positive: {
        type: "noul",
        instructions: "The review is positive.",
      },
      sentiment: {
        type: "choice",
        instructions: "What is the sentiment of the review?",
        criteria: {
          positive: "The reviewer liked the book.",
          negative: "The reviewer disliked the book.",
          neutral: "The reviewer has no strong opinion.",
        },
      },
      rating: {
        type: "score",
        instructions: "How much did the reviewer enjoy the book?",
        criteria: ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
      },
    };

    const message = await client.messages.create({
      model: "typesafe/jev-latest",
      max_tokens: 1024,
      messages: [{ role: "user", content: review }],
      // The SDK types do not know about "questions" yet, hence the cast
      output_config: { format: { type: "questions", questions } },
    } as any);

    const block = message.content[0];
    const answers = JSON.parse(block.type === "text" ? block.text : "{}");
    console.log(answers.sentiment.choice);  // "positive"
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"dark"}
    curl https://router.requesty.ai/v1/messages \
      -H "x-api-key: YOUR_REQUESTY_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "typesafe/jev-latest",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "This book was an absolute delight, I could not put it down and finished it in one sitting."
          }
        ],
        "output_config": {
          "format": {
            "type": "questions",
            "questions": {
              "positive": {
                "type": "noul",
                "instructions": "The review is positive."
              },
              "sentiment": {
                "type": "choice",
                "instructions": "What is the sentiment of the review?",
                "criteria": {
                  "positive": "The reviewer liked the book.",
                  "negative": "The reviewer disliked the book.",
                  "neutral": "The reviewer has no strong opinion."
                }
              },
              "rating": {
                "type": "score",
                "instructions": "How much did the reviewer enjoy the book?",
                "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"]
              }
            }
          }
        }
      }'
    ```
  </Tab>
</Tabs>

### Responses API

Pass the questions in `text.format`.

<Tabs>
  <Tab title="Python (OpenAI SDK)">
    ```python theme={"dark"}
    import json
    from openai import OpenAI

    client = OpenAI(
        api_key="YOUR_REQUESTY_API_KEY",
        base_url="https://router.requesty.ai/v1",
    )

    review = (
        "This book was an absolute delight, I could not put it down "
        "and finished it in one sitting."
    )

    questions = {
        "positive": {
            "type": "noul",
            "instructions": "The review is positive.",
        },
        "sentiment": {
            "type": "choice",
            "instructions": "What is the sentiment of the review?",
            "criteria": {
                "positive": "The reviewer liked the book.",
                "negative": "The reviewer disliked the book.",
                "neutral": "The reviewer has no strong opinion.",
            },
        },
        "rating": {
            "type": "score",
            "instructions": "How much did the reviewer enjoy the book?",
            "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
        },
    }

    response = client.responses.create(
        model="typesafe/jev-latest",
        input=review,
        text={"format": {"type": "questions", "questions": questions}},
    )

    answers = json.loads(response.output_text)
    print(answers["rating"]["score"])  # 4
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"dark"}
    import OpenAI from "openai";

    const client = new OpenAI({
      apiKey: "YOUR_REQUESTY_API_KEY",
      baseURL: "https://router.requesty.ai/v1",
    });

    const review =
      "This book was an absolute delight, I could not put it down and finished it in one sitting.";

    const questions = {
      positive: {
        type: "noul",
        instructions: "The review is positive.",
      },
      sentiment: {
        type: "choice",
        instructions: "What is the sentiment of the review?",
        criteria: {
          positive: "The reviewer liked the book.",
          negative: "The reviewer disliked the book.",
          neutral: "The reviewer has no strong opinion.",
        },
      },
      rating: {
        type: "score",
        instructions: "How much did the reviewer enjoy the book?",
        criteria: ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"],
      },
    };

    const response = await client.responses.create({
      model: "typesafe/jev-latest",
      input: review,
      // The SDK types do not know about "questions" yet, hence the cast
      text: { format: { type: "questions", questions } as any },
    });

    const answers = JSON.parse(response.output_text);
    console.log(answers.rating.score);  // 4
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"dark"}
    curl https://router.requesty.ai/v1/responses \
      -H "Authorization: Bearer YOUR_REQUESTY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "typesafe/jev-latest",
        "input": "This book was an absolute delight, I could not put it down and finished it in one sitting.",
        "text": {
          "format": {
            "type": "questions",
            "questions": {
              "positive": {
                "type": "noul",
                "instructions": "The review is positive."
              },
              "sentiment": {
                "type": "choice",
                "instructions": "What is the sentiment of the review?",
                "criteria": {
                  "positive": "The reviewer liked the book.",
                  "negative": "The reviewer disliked the book.",
                  "neutral": "The reviewer has no strong opinion."
                }
              },
              "rating": {
                "type": "score",
                "instructions": "How much did the reviewer enjoy the book?",
                "criteria": ["Hated it", "Disliked it", "Neutral", "Liked it", "Loved it"]
              }
            }
          }
        }
      }'
    ```
  </Tab>
</Tabs>

## Usage and billing

Jev responses report `input_tokens` and `output_tokens` in the usual `usage` block, and requests are priced and logged like any other model. See [Cost Tracking](/features/cost-tracking) and [Logs](/features/logs).

## Errors

| Status | Cause                                                                                                                    |
| ------ | ------------------------------------------------------------------------------------------------------------------------ |
| `400`  | Missing or empty `questions`, a non-`questions` response format, `stream: true`, a non-user message, or non-text content |
| `429`  | Upstream rate limit. Retry after the `Retry-After` interval                                                              |

## Related

* [Structured Outputs](/features/structured-outputs) for schema-constrained JSON from general-purpose models
* [Supported Models](/features/supported-models)
