> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt.
> For full documentation content in one file, see https://docs.sarvam.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# Open-Source Models

> Open-source models served on Sarvam infrastructure through the OpenAI-compatible chat completions API, using your existing Sarvam API key and credits.

Alongside its own models, Sarvam serves a small set of **open-source** models. You reach
them through the same chat completions API, with the same API key, credits, and rate
limits — only the `model` field changes.

**Available in beta.** GLM-5.2 and Gemma 4 31B are rolling out gradually — your API key
must be [whitelisted for beta access](/api-reference/beta-apis) before these models
respond. A key without access is refused with `400 invalid_request_error` before the
model is called. [Contact us](/api/getting-started/help) to request access.

This page focuses on the open-source models on `/v2`. The same endpoint also serves
`sarvam-105b` — see [Sarvam-105B](/api/getting-started/models/sarvam-105b).
`sarvam-105b-conversations` is on [`/v1`](/api/api-guides-tutorials/chat-completion/overview)
only. Call [`GET /v2/models`](/api-reference/open-source/models) to see which IDs your
key can use.

These models are **not tuned for Indian languages**. For Indian languages, Indic scripts,
or code-mixed input, use [Sarvam's own models](/api/getting-started/models) — they are
trained and evaluated for it. Reach for an open-source model when you need a capability
Sarvam's models do not offer, such as a very large context window or image input.

## Available models

#### [GLM-5.2](/api/getting-started/models/open-source/glm-5-2)

512K token context window with tool calling and visible reasoning. Text input only.

#### [Gemma 4 31B](/api/getting-started/models/open-source/gemma-4-31b)

Image understanding and tool calling, answering directly without a reasoning pass.

## Capabilities at a glance

| Model ID | Context window | Tool calling | Image input | Reasoning output                                        |
| -------- | -------------- | ------------ | ----------- | ------------------------------------------------------- |
| `glm5.2` | 524,288 tokens | ✅            | ❌           | ✅ always on — see [Reasoning output](#reasoning-output) |
| `gemma4` | 131,072 tokens | ✅            | ✅           | ❌ answers directly                                      |

For comparison, Sarvam's flagship chat model
[`sarvam-105b`](/api/getting-started/models/sarvam-105b) supports tool calling with 128K
context and is tuned for 23 languages (22 Indian + English).

## Using an open-source model

Open-source models are served on **`/v2/chat/completions`**. The same endpoint also
accepts `sarvam-105b`. Sarvam chat models — including `sarvam-105b-conversations` — are
on **`/v1`**; `/v1` does not accept `glm5.2` or `gemma4`.

Authentication uses the `api-subscription-key` header. A missing or invalid key is
refused with **`403 invalid_api_key_error`**. [`GET /v2/models`](/api-reference/open-source/models)
and [`GET /v2/models/{model_id}`](/api-reference/open-source/model) are unauthenticated
and list only the models available to you.

Use the [Sarvam SDK](/api/getting-started/sdks) — `client.open_source_models.chat_completions_v2(...)` in Python, or `client.openSourceModels.chatCompletionsV2(...)` in JavaScript.

#### Python

```python
from sarvamai import SarvamAI

client = SarvamAI(api_subscription_key="YOUR_SARVAM_API_KEY")

response = client.open_source_models.chat_completions_v2(
    model="glm5.2",
    messages=[
        {"role": "user", "content": "Summarise the causes of the 2008 financial crisis."}
    ],
    temperature=0.2,
    max_tokens=1000,
)

print(response.choices[0].message.content)
```

#### JavaScript

```javascript
import { SarvamAIClient } from "sarvamai";

const client = new SarvamAIClient({
    apiSubscriptionKey: "YOUR_SARVAM_API_KEY",
});

async function main() {
    const response = await client.openSourceModels.chatCompletionsV2({
        model: "glm5.2",
        messages: [
            {
                role: "user",
                content: "Summarise the causes of the 2008 financial crisis.",
            },
        ],
        temperature: 0.2,
        max_tokens: 1000,
    });

    console.log(response.choices[0].message.content);
}

main();
```

#### cURL

```bash
curl -X POST https://api.sarvam.ai/v2/chat/completions \
  -H "api-subscription-key: $SARVAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "user", "content": "Summarise the causes of the 2008 financial crisis."}
    ],
    "model": "glm5.2",
    "temperature": 0.2,
    "max_tokens": 1000
  }'
```

## Model selection

In most cases the answer is a Sarvam model — reach for an open-source model only when you
need a capability Sarvam's own models do not have.

| If you need…                                                   | Use                                                             | Why                                                                                           |
| -------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Indian languages, Indic scripts, romanised or code-mixed input | [`sarvam-105b`](/api/getting-started/models/sarvam-105b)        | Trained and evaluated for it                                                                  |
| Highest quality reasoning or agentic work                      | [`sarvam-105b`](/api/getting-started/models/sarvam-105b)        | Flagship model, Sarvam-published benchmarks                                                   |
| Wikipedia-grounded factual answers (`wiki_grounding`)          | [`sarvam-105b`](/api/getting-started/models/sarvam-105b)        | **Sarvam models only** — not available on the open-source models                              |
| More than 128K of context in one request                       | [`glm5.2`](/api/getting-started/models/open-source/glm-5-2)     | 512K context window — 4× the Sarvam chat models                                               |
| Image input with a conversational answer                       | [`gemma4`](/api/getting-started/models/open-source/gemma-4-31b) | The only chat model here that accepts images                                                  |
| Document OCR or structured extraction                          | [Sarvam Vision](/api/getting-started/models/sarvam-vision)      | Purpose-built for documents — better than `gemma4` for forms, invoices, PDFs                  |
| Visible chain-of-thought (`reasoning_content`)                 | [`glm5.2`](/api/getting-started/models/open-source/glm-5-2)     | Reasons before every answer and returns the trace — see [Reasoning output](#reasoning-output) |

The two are not interchangeable. `glm5.2` reasons before every answer but cannot see
images; `gemma4` sees images but never produces reasoning. Both support tool calling.

## Supported parameters

These models accept the same OpenAI-compatible parameters as Sarvam's chat models, with
the exceptions called out below. Support differs per model where the model itself lacks
the capability.

| Parameter                | Type             | Default                                        | `glm5.2` | `gemma4` | Notes                                                                                                                                                                                                                                      |
| ------------------------ | ---------------- | ---------------------------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `messages`               | array            | — (required)                                   | ✅        | ✅        | The conversation so far. At least one message.                                                                                                                                                                                             |
| `model`                  | string           | — (required)                                   | ✅        | ✅        | `glm5.2` or `gemma4`. Must be an id returned by [`GET /v2/models`](/api-reference/open-source/models).                                                                                                                                     |
| `max_tokens`             | integer          | `2048`                                         | ✅        | ✅        | Must be ≤ the model's context window. Estimated prompt tokens + `max_tokens` must fit inside the window, or the request is rejected with `422`. On `glm5.2` this budget also covers reasoning — see [Reasoning output](#reasoning-output). |
| `temperature`            | number           | `0.5` if `reasoning_effort` is set, else `0.2` | ✅        | ✅        | `0`–`2`. Prefer altering this **or** `top_p`, not both.                                                                                                                                                                                    |
| `top_p`                  | number           | `1`                                            | ✅        | ✅        | `>0`–`1` (`0` is rejected). Prefer altering this **or** `temperature`, not both.                                                                                                                                                           |
| `stream`                 | boolean          | `false`                                        | ✅        | ✅        | Server-sent events. Errors after the stream starts arrive as an SSE `error` frame before `[DONE]`.                                                                                                                                         |
| `stop`                   | string or array  | `null`                                         | ✅        | ✅        | Up to 4 stop sequences; not included in the output.                                                                                                                                                                                        |
| `n`                      | integer          | `1`                                            | ✅        | ✅        | `1`–`128`. You are billed for tokens across **all** choices — keep at `1` unless you need multiple completions.                                                                                                                            |
| `seed`                   | integer          | `null`                                         | ⚠️       | ✅        | Beta, best-effort determinism. In current serving `gemma4` returns identical output for an identical seed and parameters; `glm5.2` does not.                                                                                               |
| `frequency_penalty`      | number           | `0`                                            | ✅        | ✅        | `-2`–`2`. Penalises tokens by existing frequency, reducing verbatim repetition.                                                                                                                                                            |
| `presence_penalty`       | number           | `0`                                            | ✅        | ✅        | `-2`–`2`. Penalises tokens already present, encouraging new topics.                                                                                                                                                                        |
| `reasoning_effort`       | string           | `null`                                         | ✅        | ➖        | `low`, `medium`, or `high`. `glm5.2` reasons even when this is unset; `gemma4` accepts the parameter but never produces reasoning. See [Reasoning output](#reasoning-output).                                                              |
| `response_format`        | object           | `null`                                         | ✅        | ✅        | `{type: "text"}`, `{type: "json_object"}`, or `{type: "json_schema", json_schema: {...}}`. On `glm5.2`, turn thinking off — see [Structured Outputs](#structured-outputs).                                                                 |
| `tools`                  | array            | `null`                                         | ✅        | ✅        | OpenAI-compatible function calling. Max 128 tools; the model must support tools.                                                                                                                                                           |
| `tool_choice`            | string or object | `null`                                         | ✅        | ✅        | `none`, `auto`, `required`, or a named function. Requires `tools` when set to `required` or a function name — otherwise `422`.                                                                                                             |
| `extra_body`             | object           | `{}`                                           | ✅        | ✅        | Model-specific options forwarded unchanged. Must not repeat any field in this table or carry `stream_options`; a collision is rejected with `400`. Carries `chat_template_kwargs`, e.g. the thinking switch below.                         |
| `image_url` content part | object           | —                                              | ❌        | ✅        | `glm5.2` returns `400`. `gemma4` accepts **base64 data URIs only** — remote URLs are rejected. See [Image input](#image-input).                                                                                                            |

Full request and response schema: [Open-Source Models API Reference](/api-reference/open-source/chat-completions).

OpenAI-compatible fields not listed above — `logprobs`, `logit_bias`, `user`, and
similar — are accepted but ignored. Unknown fields inside `extra_body` that the model
backend does not recognise are rejected.

**`wiki_grounding` is not part of the `/v2` schema.** For
[Wikipedia grounding](/api/api-guides-tutorials/chat-completion/how-to/improve-response-factual-accuracy),
use `sarvam-105b` on `/v1`.

### Reasoning output

`glm5.2` is a reasoning model: it thinks before every answer, whether or not
`reasoning_effort` is set. The chain-of-thought arrives in a separate
`reasoning_content` field on the message — `content` holds only the final answer — and
in streaming responses it arrives as `delta.reasoning_content` chunks before the answer
starts. Reasoning tokens are billed as completion tokens and **count against
`max_tokens`**, so a budget that is too small is consumed entirely by reasoning and the
request returns `content: null` with `finish_reason: "length"`.

To turn reasoning off — faster, cheaper, and the whole budget goes to the answer — send
the thinking switch through `extra_body`:

```json
{
  "extra_body": {
    "chat_template_kwargs": { "enable_thinking": false }
  }
}
```

`gemma4` is not a reasoning model. It answers directly, never returns
`reasoning_content`, and setting `reasoning_effort` on it has no effect.

### Structured Outputs

`response_format` works on both models. Use
`{"type": "json_schema", "json_schema": {...}}` to constrain output to a JSON Schema, or
`{"type": "json_object"}` for the older JSON mode, which guarantees valid JSON but not a
specific shape.

**On `glm5.2`, turn thinking off whenever you set `response_format`** (as in the example
below). With reasoning active, a JSON-constrained request returns `content: null` — the
reasoning trace and the JSON grammar conflict, and no answer is produced. With
`enable_thinking: false` the same request returns clean JSON reliably.

#### Python

```python
import json

from sarvamai import SarvamAI

client = SarvamAI(api_subscription_key="YOUR_SARVAM_API_KEY")

response = client.open_source_models.chat_completions_v2(
    model="glm5.2",
    messages=[
        {"role": "user", "content": "List two Indian cities with their populations."}
    ],
    max_tokens=500,
    extra_body={
        "chat_template_kwargs": {"enable_thinking": False}
    },
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "city_list",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "cities": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {"type": "string"},
                                "population": {"type": "integer"},
                            },
                            "required": ["name", "population"],
                            "additionalProperties": False,
                        },
                    }
                },
                "required": ["cities"],
                "additionalProperties": False,
            },
        },
    },
)

cities = json.loads(response.choices[0].message.content)
print(cities)
```

#### JavaScript

```javascript
import { SarvamAIClient } from "sarvamai";

const client = new SarvamAIClient({
    apiSubscriptionKey: "YOUR_SARVAM_API_KEY",
});

async function main() {
    const response = await client.openSourceModels.chatCompletionsV2({
        model: "glm5.2",
        messages: [
            {
                role: "user",
                content: "List two Indian cities with their populations.",
            },
        ],
        extra_body: {
            chat_template_kwargs: { enable_thinking: false },
        },
        response_format: {
            type: "json_schema",
            json_schema: {
                name: "city_list",
                strict: true,
                schema: {
                    type: "object",
                    properties: {
                        cities: {
                            type: "array",
                            items: {
                                type: "object",
                                properties: {
                                    name: { type: "string" },
                                    population: { type: "integer" },
                                },
                                required: ["name", "population"],
                                additionalProperties: false,
                            },
                        },
                    },
                    required: ["cities"],
                    additionalProperties: false,
                },
            },
        },
    });

    const cities = JSON.parse(response.choices[0].message.content);
    console.log(cities);
}

main();
```

#### cURL

```bash
curl -X POST https://api.sarvam.ai/v2/chat/completions \
  -H "api-subscription-key: $SARVAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm5.2",
    "messages": [
      {"role": "user", "content": "List two Indian cities with their populations."}
    ],
    "extra_body": {
      "chat_template_kwargs": { "enable_thinking": false }
    },
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "city_list",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "cities": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "name": {"type": "string"},
                  "population": {"type": "integer"}
                },
                "required": ["name", "population"],
                "additionalProperties": false
              }
            }
          },
          "required": ["cities"],
          "additionalProperties": false
        }
      }
    }
  }'
```

On the Python SDK, pass `extra_body` and `response_format` as direct keyword
arguments to `chat_completions_v2` (as above). On `/v1/chat/completions`, the
chat client does not expose `response_format` as a typed parameter — use
`request_options={"additional_body_parameters": {"response_format": ...}}`
instead; see [Structured Outputs](/api/api-guides-tutorials/chat-completion/overview#structured-outputs-with-json_schema).

**Don't also ask for JSON in the prompt.** When `response_format` is set, an instruction
like "Return JSON" in the message makes `gemma4` emit whitespace until it exhausts
`max_tokens` — you are billed for the full budget and get no usable output. State the
task in the prompt and let `response_format` handle the shape.

### Image input

Only `gemma4` accepts images, and **only as base64 data URIs**. A remote `http://` or
`https://` URL is rejected — the API does not fetch images on your behalf. Full example on
the [Gemma 4 31B page](/api/getting-started/models/open-source/gemma-4-31b).

```json
{
  "type": "image_url",
  "image_url": { "url": "data:image/png;base64,<encoded bytes>" }
}
```

Each image counts against the request-size cap once encoded. Prompt and request-size
checks use estimates — text at roughly 4 bytes per token, plus a flat per-image
allowance — rather than an exact tokenizer count.

### Tool schemas

`function.parameters` must be a JSON Schema object; a property defined as a bare string
is rejected. When `tool_choice` forces a call (`required` or a named function), schemas
must be self-contained: non-local `$ref`, unresolved `$ref`, recursive schemas, or a
combined expansion above 20,000 nodes across all tools in the request are rejected with
`400`.

### Errors

Every error uses the same envelope — `error.message`, `error.code`, and
`error.request_id` (empty when the error is raised before a request id is assigned):

```json
{
  "error": {
    "message": "Model 'gpt-4' not found.",
    "code": "not_found_error",
    "request_id": "20260729_0f1e2d3c-…"
  }
}
```

| Status | Code                         | Raised when                                                                                                                                                |
| ------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_request_error`      | Body fails validation, the model lacks a requested capability, the key lacks beta access to this endpoint, or `extra_body` collides with a validated field |
| `402`  | `insufficient_quota_error`   | No credits available                                                                                                                                       |
| `403`  | `invalid_api_key_error`      | Missing or invalid API key                                                                                                                                 |
| `404`  | `not_found_error`            | Unknown model id, or a model not available to your key                                                                                                     |
| `413`  | `invalid_request_error`      | Request size exceeds the model's cap                                                                                                                       |
| `422`  | `unprocessable_entity_error` | Prompt + `max_tokens` exceeds the context window, `tool_choice` forced without `tools`, or the model rejected the request                                  |
| `429`  | `rate_limit_exceeded_error`  | Rate or concurrency limit; may carry `Retry-After`                                                                                                         |
| `500`  | `internal_server_error`      | Unhandled failure                                                                                                                                          |
| `502`  | `model_call_failed`          | The model call failed and could not be retried                                                                                                             |
| `503`  | `model_overloaded`           | Timeout, connection failure, or overload after automatic retries                                                                                           |

Timeouts, connection failures, and overload are retried automatically before a `503` is
returned. A request the model itself rejects is not retried and comes back as `422`.

## Support and expectations

#### What Sarvam supports

Sarvam supports the serving layer: availability, authentication, billing, rate
limits, and API compatibility. If a request fails with a Sarvam error — an auth
failure, a rate limit, a credits problem, a malformed response from our gateway —
[contact us](/api/getting-started/help).

#### What Sarvam does not support

Sarvam does not tune, evaluate, or publish benchmarks for these models, and does not
guarantee their output quality. A model's reasoning, factual accuracy, language
coverage, and refusals are properties of the model itself rather than of Sarvam's
serving.

#### Availability and versioning

These models may be updated, versioned, or withdrawn on a different schedule from
Sarvam's own models. Do not assume one of these model IDs is a long-term stable
contract — check the [changelog](/api/getting-started/changelog) before depending on
one in production.

#### Licensing and terms

Each model carries its own open-source licence and acceptable-use terms, which apply
to you as the end user in addition to Sarvam's terms. Review the model's licence
before using it in a commercial product.

## Shared behaviour

Everything below applies to both models:

* **Endpoint** — `POST https://api.sarvam.ai/v2/chat/completions`. Full parameter
  reference: [Open-Source Models API Reference](/api-reference/open-source/chat-completions).
* **Model discovery** — [`GET https://api.sarvam.ai/v2/models`](/api-reference/open-source/models)
  lists the model IDs the endpoint currently serves.
* **Authentication** — `api-subscription-key: sk_xxx`. Invalid keys return
  `403 invalid_api_key_error`. See [Authentication](/api-reference/authentication).
* **Beta access** — granted per key. Without access, the endpoint returns
  `400 invalid_request_error` before calling the model. See
  [Access to Beta APIs](/api-reference/beta-apis).
* **Streaming** — set `"stream": true` for server-sent events.
* **Billing** — metered per token against your Sarvam credits, reasoning tokens
  included. Per 1M tokens (input / cached input / output): `gemma4` ₹36.6 / ₹13.73 / ₹91.5,
  `glm5.2` ₹128.1 / ₹23.79 / ₹402.6. The two are not priced alike — `glm5.2` costs roughly
  3.5× `gemma4`, and it reasons before every answer, so budget `max_tokens` deliberately.
  See [Pricing](/api/getting-started/pricing).
* **Rate limits** — applied per API key. See [Credits & Rate Limits](/api/getting-started/ratelimits).