Repository: huggingface/transformers
Pull request: fix: resolve triton version check compatibility on windows

# What does this PR do?

<!--
Congratulations! You've made it this far! You're not quite done yet though.

Once merged, your PR is going to appear in the release notes with the title you set, so make sure it's a great title that fully reflects the extent of your awesome contribution.

Then, please replace this with a description of the change and which issue is fixed (if applicable). Please also include relevant motivation and context. List any dependencies (if any) that are required for this change.

Once you're done, someone will review your PR shortly (see the section "Who can review?" below to tag some potential reviewers). They may suggest changes to make the code even better. If no one reviewed your PR after a week has passed, don't hesitate to post a new comment @-mentioning the same persons---sometimes notifications get lost.
-->

<!-- Remove if not applicable -->

This PR fixes https://github.com/huggingface/transformers/issues/39985

## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [x] Did you read the [contributor guideline](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#create-a-pull-request),
      Pull Request section?
- [x] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [ ] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/transformers/tree/main/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/transformers/tree/main/docs#writing-source-documentation).
- [x] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

<!-- Your PR will be replied to more quickly if you can figure out the right person to tag with @

 If you know how to use git blame, that is the easiest way, otherwise, here is a rough guide of **who to tag**.
 Please tag fewer than 3 people.

Models:

- text models: @ArthurZucker
- vision models: @amyeroberts, @qubvel
- speech models: @eustlb
- graph models: @clefourrier

Library:

- flax: @gante and @Rocketknight1
- generate: @zucchini-nlp (visual-language models) or @gante (all others)
- pipelines: @Rocketknight1
- tensorflow: @gante and @Rocketknight1
- tokenizers: @ArthurZucker
- trainer: @zach-huggingface, @SunMarc and @qgallouedec
- chat templates: @Rocketknight1

Integrations:

- deepspeed: HF Trainer/Accelerate: @SunMarc @zach-huggingface
- ray/raytune: @richardliaw, @amogkam
- Big Model Inference: @SunMarc
- quantization (bitsandbytes, autogpt): @SunMarc @MekkCyber

Documentation: @stevhliu

HF projects:

- accelerate: [different repo](https://github.com/huggingface/accelerate)
- datasets: [different repo](https://github.com/huggingface/datasets)
- diffusers: [different repo](https://github.com/huggingface/diffusers)
- rust tokenizers: [different repo](https://github.com/huggingface/tokenizers)

Maintained examples (not research project or legacy):

- Flax: @Rocketknight1
- PyTorch: See Models above and tag the person corresponding to the modality of the example.
- TensorFlow: @Rocketknight1

 -->

## Summary
This PR adds support for detecting `triton-windows` in the version-check logic inside [`transformers/utils/import_utils.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/utils/import_utils.py).

Currently, when `triton-windows` is installed on Windows, the following check fails:

```python
importlib.metadata.version("pytorch-triton")
```
As a result, MXFP4 quantization in models like [openai/gpt-oss-20b](https://huggingface.co/openai/gpt-oss-20b) falls back to `bf16` unnecessarily, leading to significant inference time delay due to CPU offloading.

This PR is compatible with Triton on both Windows and Linux, and also remain checking `pytorch-triton` when `triton` is not found, enabling MXFP4 inference on all devices.

## Test
### test code
Here time count is introduced to show the difference before and after bug fix. The inference speed of [openai/gpt-oss-20b](https://huggingface.co/openai/gpt-oss-20b) increased by 16 times on a NVIDIA GeForce RTX 5090 GPU.
```python
from transformers import pipeline
import torch
import time

model_id = "openai/gpt-oss-20b"

pipe = pipeline(
    "text-generation",
    model=model_id,
    torch_dtype="auto",
    device_map="auto"
)

messages = [
    {"role": "user", "content": "Explain quantum mechanics clearly and concisely."},
]

time_start = time.time()

outputs = pipe(
    messages,
    max_new_tokens=1024,
)

time_end = time.time()

print(outputs[0]["generated_text"][-1])
print(f"Time Cost: {time_end - time_start} seconds")
```

### Before
On Windows with `triton-windows` >= 3.4.0 installed:
MXFP4 fallback warning appears and Inference is very slow due to CPU offload:

```
MXFP4 quantization requires triton >= 3.4.0 and triton_kernels installed, we will default to dequantizing the model to bf16
Loading checkpoint shards: 100%|████████████████████████████████████████████████████████| 3/3 [00:12<00:00,  4.19s/it] 
Some parameters are on the meta device because they were offloaded to the cpu.
Device set to use cuda:0
{'role': 'assistant', 'content': 'analysisThe user asks: "Explain quantum mechanics clearly and concisely." They likely want a concise but clear explanation. They want a balanced explanation: basics, key concepts, maybe mention wave-particle duality, superposition, uncertainty, measurement, wavefunction, etc. They want clear and concise. Probably a few paragraphs. They might appreciate analogies. So respond with a concise explanation, maybe bullet points, short sentences. Should avoid jargon. Provide an accessible overview. Probably mention that quantum mechanics is the physics of microscopic scales, describes particles as waves, probability, superposition, entanglement, etc. Also mention that classical mechanics emerges as approximation at larger scales. Keep it clear. Also mention that mathematics: Schrödinger equation, operators. Maybe mention the significance: quantum computing, electronics. So produce a concise explanation. Use simple language. I\'ll produce 3-4 paragraphs or bullet points. Ensure clarity.assistantfinal**Quantum mechanics in a nutshell**\n\n| Core idea | What it means for “tiny” objects |\n|-----------|----------------------------------|\n| **Wave‑particle duality** | Electrons, photons, atoms behave sometimes like tiny balls, sometimes like waves that interfere. |\n| **Wavefunction (ψ)** | A mathematical “wave” that tells you the probability of finding the particle where you look. |\n| **Superposition** | Until you measure it, a quantum system can be in many states at once (e.g., a cat that’s both alive and dead in Schrödinger’s thought experiment). |\n| **Uncertainty principle** | You can’t know position *and* momentum exactly at the same time; the more precisely you know one, the fuzzier the other becomes. |\n| **Measurement collapses the wavefunction** | When you look, the spread of possibilities “collapses” to a single result. |\n| **Entanglement** | Two particles can share a single wavefunction, so measuring one instantly tells you about the other, no matter how far apart. |\n\n**Why it matters**\n\n- **Microscopic physics**: Explains how atoms bond, how semiconductors work, why the Sun shines.  \n- **Technology**: Quantum bits (qubits) in quantum computers, quantum cryptography, MRI imaging.  \n- **Emergence of classical physics**: For large objects the many tiny quantum effects average out, giving us the smooth, predictable world of everyday mechanics.\n\n**Basic picture**\n\n1. **Prepare** a quantum system (e.g., put an electron in a known energy state).  \n2. **Let it evolve** according to the Schrödinger equation – the wavefunction spreads, interferes, and changes in time.  \n3. **Measure** – you get a definite outcome, and the wavefunction “collapses” to that result.  \n4. **Repeat** – the statistical pattern of many measurements matches the probabilities predicted by the wavefunction.\n\nThat is quantum mechanics: a probabilistic, wave‑based theory that replaces the deterministic, Newtonian view for the very small.'}
Time Cost: 471.1367383003235 seconds
```

### After
On Windows with `triton-windows` >= 3.4.0 installed:
- [x] Version is correctly detected with no warnings
- [x] MXFP4 quantization is enabled
- [x] Inference runs efficiently on GPU

```
Loading checkpoint shards: 100%|████████████████████████████████████████████████████████| 3/3 [00:04<00:00,  1.56s/it] 
Device set to use cuda:0
{'role': 'assistant', 'content': 'analysisThe user asks: "Explain quantum mechanics clearly and concisely." They want a concise explanation. We should explain key concepts: wave-particle duality, superposition, measurement, entanglement, Heisenberg uncertainty, Schrödinger equation, probabilities, collapse, quantum states, operators. Should be clear, accessible. Probably 200-300 words. Should avoid jargon. Provide intuitive analogies. Use bullet points maybe. Let\'s produce a concise explanation.assistantfinal**Quantum mechanics in a nutshell**\n\n| What it studies | How it works | Why it matters |\n|-----------------|--------------|----------------|\n| **The microscopic world** – atoms, electrons, photons, nuclei | **Probabilities, not certainties** – a particle is described by a *wavefunction* that gives the chance of finding it anywhere. | Explains all of chemistry, electronics, lasers, MRI, and the behavior of the most fundamental building blocks of the universe. |\n\n### Core ideas\n\n1. **Wave–particle duality**  \n   *Light and matter act both like particles (they have mass or energy) and like waves (they interfere and diffract).*  \n   *Analogy:* A drop of ink in water spreads out like a wave but still travels as a lump.\n\n2. **Quantum state and superposition**  \n   A system can be in a *superposition* of many possible states at once.  \n   *Example:* An electron in an atom can be in a mix of “up” and “down” spin until measured.\n\n3. **Measurement collapses the wavefunction**  \n   When we observe a property, the superposition instantaneously “collapses” to a single outcome.  \n   *Result:* We get a definite number (e.g., the electron is found in one particular location), but the exact outcome was only probabilistic beforehand.\n\n4. **Entanglement**  \n   Two or more particles can become linked so that the state of one instantly determines the state of the other, no matter how far apart.  \n   *Implication:* Correlations that defy classical explanations.\n\n5. **Uncertainty principle**  \n   Certain pairs of properties (position & momentum, energy & time) cannot both be known exactly at the same time.  \n   *Consequence:* The world is fundamentally fuzzy at small scales.\n\n6. **Schrödinger equation**  \n   Governs how a wavefunction evolves over time:  \n   \\[\n   i\\hbar\\,\\frac{\\partial\\psi}{\\partial t} = \\hat H \\psi\n   \\]  \n   *What it does:* Predicts probabilities for all possible outcomes.\n\n### Why the weirdness works\n\n- **Probability amplitudes** (complex numbers) interfere, producing the characteristic patterns of double‑slit experiments.  \n- **Operators** represent measurable quantities; their eigenvalues are the possible results.  \n- **Observables** are linked to physical experiments, not to hidden “true” values.\n\nIn practice, quantum mechanics tells us how to design semiconductors, explain chemical bonds, predict the spectrum of atoms, and even build quantum computers that exploit superposition and entanglement for computation far beyond classical machines. The theory is mathematically precise, experimentally verified to extraordinary accuracy, and the only framework we have for describing the behavior of matter and energy at the smallest scales.'}
Time Cost: 29.460687398910522 seconds
```


Changed files:
filename: src/transformers/utils/import_utils.py
patch: @@ -78,9 +78,14 @@ def _is_package_available(pkg_name: str, return_version: bool = False) -> Union[
                     package_exists = False
             elif pkg_name == "triton":
                 try:
-                    package_version = importlib.metadata.version("pytorch-triton")
+                    # import triton works for both linux and windows
+                    package = importlib.import_module(pkg_name)
+                    package_version = getattr(package, "__version__", "N/A")
                 except Exception:
-                    package_exists = False
+                    try:
+                        package_version = importlib.metadata.version("pytorch-triton")  # pytorch-triton
+                    except Exception:
+                        package_exists = False
             else:
                 # For packages other than "torch", don't attempt the fallback and set as not available
                 package_exists = False