Skip to main content

A Flask-based inference server optimized for Google Cloud TPU v5e

Project description

TPU Inference Server

A Flask-based inference server optimized for Google Cloud TPU v5e. Supports multiple models, dynamic loading/unloading, and provides OpenAI-compatible API endpoints.

Installation

From PyPI (recommended)

pip install tpu-inference-server

From Source

git clone https://github.com/yourusername/tpu-inference-server.git
cd tpu-inference-server
pip install -e .

TPU Dependencies

PyTorch XLA for TPU must be installed separately from Google's index:

pip install torch torch_xla \
  -f https://storage.googleapis.com/libtpu-releases/index.html \
  -f https://storage.googleapis.com/libtpu-wheels/index.html

Or use the setup script on a TPU VM:

./setup.sh

Features

  • TPU Optimized: Uses PyTorch XLA with manual token generation for reliable TPU inference
  • Multiple Models: Load and serve multiple models simultaneously
  • Dynamic Loading: Load/unload models at runtime via API
  • OpenAI Compatible: /v1/chat/completions endpoint works with OpenAI client libraries
  • Memory Efficient: Uses bfloat16 by default for 7B parameter models
  • XLA Warmup: Automatic warmup step to pre-compile XLA graphs
  • CLI Tool: Easy-to-use command-line interface
  • Python Client: Built-in client library for programmatic access

Supported Models

Model ID Recommended dtype Memory
Mistral 7B mistralai/Mistral-7B-Instruct-v0.2 bfloat16 ~14GB
Llama 2 7B meta-llama/Llama-2-7b-chat-hf bfloat16 ~14GB
Gemma 2B google/gemma-2b-it bfloat16 ~4GB
GPT-2 gpt2 float32 ~0.5GB

Quick Start

CLI Usage

# Generate example config file
tpu-server init-config

# Start server with config
tpu-server serve --config config.yaml

# Start with specific model
tpu-server serve --model gpt2 --model-name gpt2 --dtype float32

# Start with custom host/port
tpu-server serve --host 0.0.0.0 --port 9000

Python Usage

from tpu_inference_server import TPUInferenceServer, TPUInferenceClient

# Start server programmatically
server = TPUInferenceServer(port=8080)
server.load_model("gpt2", "gpt2", "float32")
server.run()
# Use the client
from tpu_inference_server import TPUInferenceClient

client = TPUInferenceClient("http://localhost:8080")

# Check health
print(client.health())

# Generate text
result = client.generate("Hello, world!", max_new_tokens=50)
print(result["generated_text"])

# Chat completion
response = client.chat_simple("What is Python?", max_tokens=100)
print(response)

Module Execution

python -m tpu_inference_server serve --model gpt2

Google Cloud TPU Setup

1. Create a TPU v5e Instance

# Create TPU v5e-4 (4 chips)
gcloud compute tpus queued-resources create my-tpu-qr \
    --node-id=my-tpu \
    --zone=us-central1-a \
    --accelerator-type=v5litepod-4 \
    --runtime-version=v2-alpha-tpuv5-lite

# Wait for TPU to be ready
gcloud compute tpus queued-resources describe my-tpu-qr \
    --zone=us-central1-a

# SSH into the TPU VM
gcloud compute tpus tpu-vm ssh my-tpu --zone=us-central1-a

2. Install and Run

# Install the package
pip install tpu-inference-server

# Install TPU dependencies
pip install torch torch_xla \
  -f https://storage.googleapis.com/libtpu-releases/index.html \
  -f https://storage.googleapis.com/libtpu-wheels/index.html

# Generate config
tpu-server init-config

# Start server
tpu-server serve

API Reference

Note: The first request after loading a model will take longer (30-60+ seconds) as XLA compiles the computation graph. Subsequent requests will be much faster.

Health Check

curl http://localhost:8080/health

Response:

{
  "status": "healthy",
  "device": "xla:0",
  "loaded_models": ["mistral-7b"],
  "timestamp": "2024-01-15T10:30:00"
}

List Models

curl http://localhost:8080/models

Load Model Dynamically

curl http://localhost:8080/models/load \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"model_id": "gpt2", "name": "gpt2", "dtype": "float32"}'

Unload Model

curl http://localhost:8080/models/unload \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"name": "gpt2"}'

Generate Text

curl http://localhost:8080/generate \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": "What is artificial intelligence?",
    "model": "mistral-7b",
    "max_new_tokens": 100,
    "temperature": 0.7
  }'

Response:

{
  "generated_text": "Artificial intelligence (AI) is...",
  "model": "mistral-7b",
  "usage": {"max_new_tokens": 100}
}

OpenAI-Compatible Chat Completions

curl http://localhost:8080/v1/chat/completions \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-7b",
    "messages": [
      {"role": "user", "content": "Hello, how are you?"}
    ],
    "max_tokens": 50,
    "temperature": 0.7
  }'

Response:

{
  "id": "chatcmpl-1705312200",
  "object": "chat.completion",
  "created": 1705312200,
  "model": "mistral-7b",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "Hello! I'm doing well, thank you for asking..."
    },
    "finish_reason": "stop"
  }]
}

OpenAI-Compatible Models List

curl http://localhost:8080/v1/models

Configuration

config.yaml

server:
  host: "0.0.0.0"    # Bind address
  port: 8080          # Port number

models:
  - model_id: "mistralai/Mistral-7B-Instruct-v0.2"
    name: "mistral-7b"     # Name to reference model by
    dtype: "bfloat16"      # bfloat16, float32, or float16

CLI Options

tpu-server serve --help

Options:
  --config, -c     Path to config file (default: config.yaml)
  --host           Host to bind (default: 0.0.0.0)
  --port, -p       Port to bind (default: 8080)
  --model, -m      Model ID to load on startup
  --model-name     Name for the model
  --dtype          Data type: bfloat16, float32, float16 (default: bfloat16)
  --no-warmup      Skip warmup step on model load
  --debug          Enable debug mode

External Access

Create Firewall Rule

gcloud compute firewall-rules create allow-inference-8080 \
  --allow tcp:8080 \
  --source-ranges="0.0.0.0/0" \
  --description="Allow inference server access"

Get External IP

# From the TPU VM
curl -s ifconfig.me

Access from External Client

curl http://<EXTERNAL_IP>:8080/health

Memory Requirements

TPU Type HBM Memory Recommended Models
v5litepod-1 16GB Gemma 2B, GPT-2
v5litepod-4 64GB Mistral 7B, Llama 2 7B, multiple small models
v5litepod-8 128GB Multiple 7B models, 13B models

Using with OpenAI Python Client

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="not-needed"  # API key not required for local server
)

response = client.chat.completions.create(
    model="mistral-7b",
    messages=[
        {"role": "user", "content": "Hello!"}
    ],
    max_tokens=50
)

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

Troubleshooting

"No TPU devices found"

Ensure you're running on a TPU VM:

ls /dev/accel*

Verify TPU is healthy:

gcloud compute tpus tpu-vm describe my-tpu --zone=us-central1-a

"Out of memory"

  • Use bfloat16 instead of float32
  • Load fewer models simultaneously
  • Try a smaller model (Gemma 2B, GPT-2)

Slow first request

This is normal - XLA needs to compile the graph. The warmup step reduces this, but the first real request may still be slower.

"XLA compilation failed"

Ensure you're using the correct PyTorch XLA version:

pip install torch torch_xla \
  -f https://storage.googleapis.com/libtpu-releases/index.html \
  -f https://storage.googleapis.com/libtpu-wheels/index.html

Model download fails

For gated models (Llama 2), you need to:

  1. Accept the license on HuggingFace
  2. Login: huggingface-cli login

Cleanup

Delete TPU Resources

# Delete TPU
gcloud compute tpus queued-resources delete my-tpu-qr \
  --zone=us-central1-a \
  --force \
  --quiet

# Delete firewall rule (optional)
gcloud compute firewall-rules delete allow-inference-8080 --quiet

Architecture Notes

Why Manual Token Generation?

The standard model.generate() method in Transformers has known issues with XLA/TPU:

  • Causes excessive recompilation
  • Can hang or produce incorrect outputs
  • Memory usage is unpredictable

This server uses a manual generation loop that:

  • Calls the model forward pass directly
  • Uses xm.mark_step() after each token
  • Provides predictable memory usage and performance

Why Single-Threaded Flask?

TPU/XLA requires single-threaded execution:

  • XLA compilation is not thread-safe
  • Model state cannot be shared across threads safely
  • Flask's threaded=False ensures correct behavior

For production deployments with high concurrency, consider:

  • Running multiple server instances behind a load balancer
  • Using a queue-based architecture

Development

Install dev dependencies

pip install -e ".[dev]"

Run tests

pytest

Format code

black src/
ruff check src/ --fix

Contributing

See CONTRIBUTING.md for guidelines on how to contribute.

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tpu_inference_server-0.1.1.tar.gz (27.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tpu_inference_server-0.1.1-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file tpu_inference_server-0.1.1.tar.gz.

File metadata

  • Download URL: tpu_inference_server-0.1.1.tar.gz
  • Upload date:
  • Size: 27.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for tpu_inference_server-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b96ca60eaaf1b5838bbc6e4fc547f756c8334ed5ec8f24e8b2b73b637466b27e
MD5 1375af987336edac910a149294426f6b
BLAKE2b-256 e6bb3643532ff37a0d2738f7f08022588acefa8a8f27f9e1df1444297e786a03

See more details on using hashes here.

File details

Details for the file tpu_inference_server-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for tpu_inference_server-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 09ca9a073fc7c99b744112dad8a7669614bf77574eba939a16f043f8fce60731
MD5 0aed1752502c113ebca99fbd1d9e3776
BLAKE2b-256 4a134d8290add27bd4e67b730381c4b34819d1f279b1838fc675045bf2a26ce7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page