> ## Documentation Index
> Fetch the complete documentation index at: https://modular-main.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Text generation

> Generate text from an LLM using text, image, and video inputs

To generate text with an LLM, you need to use the [chat completions
API](/api/inference/create-chat-completion). This API allows you to send text,
images, and videos with your request, using an OpenAI-compatible interface,
as shown in the following examples.

The examples below use the `minimax-m3` model, but you can replace it with any
[supported model](/models) that's listed as an "LLM" type.

## Requirements

* An [API key](/administration/api-keys). The code below assumes you set it
  in an environment variable:

  <CodeGroup>
    ```bash macOS/Linux theme={null}
    export MODULAR_API_KEY="your_api_key"
    ```

    ```bash Windows theme={null}
    $env:MODULAR_API_KEY="your_api_key"
    ```
  </CodeGroup>

* The `openai` Python package. You can install it with this command:

  <CodeGroup>
    ```bash Python (pip) theme={null}
    pip install openai
    ```

    ```bash Python (uv) theme={null}
    uv add openai
    ```

    ```bash Python (pixi) theme={null}
    pixi add openai
    ```

    ```bash TypeScript (npm) theme={null}
    npm install openai
    ```
  </CodeGroup>

## Generate a text response

Here's how you can generate text from a prompt or conversation history.

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.modular.com/v1",
      api_key=os.environ.get("MODULAR_API_KEY"),
  )

  response = client.chat.completions.create(
      model="minimax/minimax-m3",
      messages=[
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Who won the world series in 2020?"},
          {"role": "assistant", "content": "The LA Dodgers won in 2020."},
          {"role": "user", "content": "Where was it played?"}
      ]
  )
  print(response.choices[0].message.content)
  ```

  ```typescript TypeScript theme={null}
  import process from "node:process";
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.modular.com/v1",
    apiKey: process.env.MODULAR_API_KEY,
  });

  async function main() {
    const response = await client.chat.completions.create({
      model: "minimax/minimax-m3",
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: "Who won the world series in 2020?" },
        { role: "assistant", content: "The LA Dodgers won in 2020." },
        { role: "user", content: "Where was it played?" },
      ],
    });

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

  main();
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.modular.com/v1/chat/completions \
    -H "Authorization: Bearer $MODULAR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "minimax/minimax-m3",
      "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The LA Dodgers won in 2020."},
        {"role": "user", "content": "Where was it played?"}
      ]
    }'
  ```
</CodeGroup>

## Stream a text response

Set `stream=True` to receive tokens as they are generated instead of waiting
for the full response.

<CodeGroup>
  ```python Python highlight={12} theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.modular.com/v1",
      api_key=os.environ.get("MODULAR_API_KEY"),
  )

  stream = client.chat.completions.create(
      model="minimax/minimax-m3",
      messages=[{"role": "user", "content": "Write a short poem about the sea."}],
      stream=True,
  )

  for chunk in stream:
      if not chunk.choices:
          continue
      content = chunk.choices[0].delta.content
      if content is not None:
          print(content, end="", flush=True)
  print()
  ```

  ```typescript TypeScript highlight={13} theme={null}
  import process from "node:process";
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.modular.com/v1",
    apiKey: process.env.MODULAR_API_KEY,
  });

  async function main() {
    const stream = await client.chat.completions.create({
      model: "minimax/minimax-m3",
      messages: [{ role: "user", content: "Write a short poem about the sea." }],
      stream: true,
    });

    for await (const chunk of stream) {
      process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
    }
    process.stdout.write("\n");
  }

  main();
  ```

  ```bash cURL highlight={7} theme={null}
  curl -X POST https://api.modular.com/v1/chat/completions \
      -H "Authorization: Bearer $MODULAR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "minimax/minimax-m3",
        "messages": [{"role": "user", "content": "Write a short poem about the sea."}],
        "stream": true
      }'
  ```
</CodeGroup>

## Analyze an image

Some LLMs accept images, allowing them to generate a description or analysis of
the image visual content. You can use any [supported model](/models) that's
both an "LLM" and a "Vision" type.

To pass an image, add the `image_url` attribute in the `messages.content`
object. The inner `url` attribute accepts either a publicly accessible URL or a
base64-encoded data URI (for example, `data:image/jpeg;base64,...`).

Notice that `content` is an array, allowing you to pass multiple images at
once.

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.modular.com/v1",
      api_key=os.environ.get("MODULAR_API_KEY"),
  )

  response = client.chat.completions.create(
      model="minimax/minimax-m3",
      messages=[
          {
              "role": "user",
              "content": [
                  {"type": "text", "text": "What is in this image?"},
                  {
                      "type": "image_url",
                      "image_url": {
                          "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/0052a70beed5bf71b92610a43a52df6d286cd5f3/diffusers/rabbit.jpg"
                      },
                  },
              ],
          }
      ],
      max_tokens=300,
  )

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

  ```typescript TypeScript theme={null}
  import process from "node:process";
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.modular.com/v1",
    apiKey: process.env.MODULAR_API_KEY,
  });

  async function main() {
    const response = await client.chat.completions.create({
      model: "minimax/minimax-m3",
      messages: [
        {
          role: "user",
          content: [
            {
              type: "text",
              text: "What is in this image?",
            },
            {
              type: "image_url",
              image_url: {
                url: "https://huggingface.co/datasets/huggingface/documentation-images/resolve/0052a70beed5bf71b92610a43a52df6d286cd5f3/diffusers/rabbit.jpg",
              },
            },
          ],
        },
      ],
      max_tokens: 300,
    });

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

  main();
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.modular.com/v1/chat/completions \
    -H "Authorization: Bearer $MODULAR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "minimax/minimax-m3",
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": "What is in this image?"
            },
            {
              "type": "image_url",
              "image_url": {
                "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/0052a70beed5bf71b92610a43a52df6d286cd5f3/diffusers/rabbit.jpg"
              }
            }
          ]
        }
      ],
      "max_tokens": 300
    }' | grep -o '"content":"[^"]*"' | sed 's/"content":"//g' | sed 's/"//g' | tr -d '\n' | sed 's/\\n/\n/g'
  ```
</CodeGroup>

## Analyze a video

Some LLMs accept video input, allowing them to generate a description or
analysis of the video's visual content. You can use any [supported
model](/models) that's both an "LLM" and a "Vision" type.

To pass a video, add the `video_url` attribute in the `messages.content`
object. The inner `url` attribute accepts either a publicly accessible URL or a
base64-encoded data URI (for example, `data:video/mp4;base64,...`).

Notice that `content` is an array, allowing you to pass multiple videos at
once, or even a combination of videos and images.

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.modular.com/v1",
      api_key=os.environ.get("MODULAR_API_KEY"),
  )

  completion = client.chat.completions.create(
      model="minimax/minimax-m3",
      messages=[
          {
              "role": "user",
              "content": [
                  {"type": "text", "text": "Describe what is happening in this video"},
                  {
                      "type": "video_url",
                      "video_url": {
                          "url": "https://avtshare01.rz.tu-ilmenau.de/avt-vqdb-uhd-1/test_1/segments/bigbuck_bunny_8bit_15000kbps_1080p_60.0fps_h264.mp4"
                      },
                  },
              ],
          }
      ],
      max_tokens=300,
      # minimax-m3 uses adaptive thinking by default, which can consume the entire
      # token budget when analyzing videos, leaving message.content empty.
      extra_body={"reasoning": {"enabled": False}},
  )

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

  ```typescript TypeScript theme={null}
  import process from "node:process";
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.modular.com/v1",
    apiKey: process.env.MODULAR_API_KEY,
  });

  async function main() {
    const response = await client.chat.completions.create({
      model: "minimax/minimax-m3",
      messages: [
        {
          role: "user",
          content: [
            {
              type: "text",
              text: "Describe what is happening in this video",
            },
            {
              type: "video_url",
              video_url: {
                url: "https://avtshare01.rz.tu-ilmenau.de/avt-vqdb-uhd-1/test_1/segments/bigbuck_bunny_8bit_15000kbps_1080p_60.0fps_h264.mp4",
              },
            },
          ],
        },
      ],
      max_tokens: 300,
      // minimax-m3 uses adaptive thinking by default, which can consume the entire
      // token budget when analyzing videos, leaving message.content empty.
      reasoning: { enabled: false },
    } as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);

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

  main();
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.modular.com/v1/chat/completions \
    -H "Authorization: Bearer $MODULAR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "minimax/minimax-m3",
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": "Describe what is happening in this video"
            },
            {
              "type": "video_url",
              "video_url": {
                "url": "https://avtshare01.rz.tu-ilmenau.de/avt-vqdb-uhd-1/test_1/segments/bigbuck_bunny_8bit_15000kbps_1080p_60.0fps_h264.mp4"
              }
            }
          ]
        }
      ],
      "max_tokens": 300,
      "reasoning": {"enabled": false}
    }' | grep -o '"content":"[^"]*"' | sed 's/"content":"//g' | sed 's/"//g' | tr -d '\n' | sed 's/\\n/\n/g'
  ```
</CodeGroup>
