Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/specs/feature-usage-bit-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ only to approved first-party endpoints.
| 86 | `hosting.responses` | OpenAI Responses hosting converters | `agent_framework_hosting_responses.responses_to_run` |
| 87 | `hosting.telegram` | Telegram hosting converters | `agent_framework_hosting_telegram.telegram_to_run` |
| 88 | `lab` | Experimental Agent Framework Lab features | `agent_framework.lab` feature entry points |
| 89–127 | _reserved_ | future packages | — |
| 89 | `nvidia` | NVIDIA NIM embedding client | `agent_framework_nvidia.NvidiaEmbeddingClient` |
| 90–127 | _reserved_ | future packages | — |

## Index table — .NET (`agent-framework-dotnet`, version 1)

Expand Down
1 change: 1 addition & 0 deletions python/PACKAGE_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ column records whether `pip install agent-framework` installs the workspace pack
| `agent-framework-mistral` | `python/packages/mistral` | `beta` | `yes` |
| `agent-framework-mongodb` | `python/packages/mongodb` | `alpha` | `no` |
| `agent-framework-monty` | `python/packages/monty` | `beta` | `yes` |
| `agent-framework-nvidia` | `python/packages/nvidia` | `alpha` | `no` |
| `agent-framework-ollama` | `python/packages/ollama` | `beta` | `yes` |
| `agent-framework-openai` | `python/packages/openai` | `released` | `yes` |
| `agent-framework-oracle` | `python/packages/oracle` | `alpha` | `no` |
Expand Down
49 changes: 49 additions & 0 deletions python/packages/nvidia/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# NVIDIA Package (agent-framework-nvidia)

Integration with NVIDIA NIM for embedding generation.

## Implementation Notes

- NVIDIA NIM exposes an OpenAI-compatible endpoint, so this package builds on
`RawOpenAIEmbeddingClient` from `agent-framework-openai` rather than reimplementing the wire
format. This mirrors `agent-framework-foundry-local`, which builds on the OpenAI Chat
Completions client for the same reason.
- The default endpoint is `https://integrate.api.nvidia.com/v1`. `base_url` overrides it, which is
the hook for a self-hosted NIM container.
- Model availability is per-account. An unentitled model returns `404 ... Not found for account`,
and a retired model returns `410 Gone`, so neither is a request-shape error.
- `input_type` and `truncate` are outside the OpenAI embedding schema. The client sends them as
`extra_body` by overriding `_prepare_extra_request_options`, and rejects invalid values before
the request. Callers set `input_type` per call through vector-store `embeddings_options`, the
same route the Gemini client uses for `task_type`. An `agent-framework-openai` without that hook
would drop both fields silently, so importing the package raises `ImportError` instead.
- The hosted endpoint rejects requests with more than 256 inputs (`MAX_BATCH_SIZE`) or a body over
2 MiB (`413`, budgeted by `MAX_BATCH_BYTES`), and a vector-store upsert embeds every record in one
call, so `get_embeddings` splits larger inputs into consecutive requests, as the Gemini client does
for Enterprise.

## Main Classes

- **`NvidiaEmbeddingClient`** - Embedding client for NVIDIA NIM models, with telemetry
- **`RawNvidiaEmbeddingClient`** - The same client without the telemetry layer
- **`NvidiaEmbeddingOptions`** - Options TypedDict for NVIDIA-specific embedding parameters
- **`NvidiaEmbeddingSettings`** - TypedDict settings for NVIDIA configuration

## Usage

```python
from agent_framework_nvidia import NvidiaEmbeddingClient

# Requires NVIDIA_API_KEY environment variable (or pass api_key= directly)
client = NvidiaEmbeddingClient(model="nvidia/nemotron-3-embed-1b")
result = await client.get_embeddings(["Hello, world!"])
print(result[0].vector)
```

## Import Path

The package is alpha, so there is no `agent_framework.nvidia` namespace in core yet.

```python
from agent_framework_nvidia import NvidiaEmbeddingClient
```
21 changes: 21 additions & 0 deletions python/packages/nvidia/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) Microsoft Corporation.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
86 changes: 86 additions & 0 deletions python/packages/nvidia/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Get Started with Microsoft Agent Framework NVIDIA NIM

An alpha NVIDIA NIM embedding integration for Microsoft Agent Framework. Please install this package:

```bash
pip install agent-framework-nvidia --pre
```

and see the [README](https://github.com/microsoft/agent-framework/tree/main/python/README.md) for more information.

See the [NVIDIA samples](samples/README.md) for a runnable example.

## Embedding Client

The `NvidiaEmbeddingClient` provides embedding generation using models hosted on
[NVIDIA NIM](https://build.nvidia.com/). NIM exposes an OpenAI-compatible surface, so this client
builds on the OpenAI embedding client rather than reimplementing the wire format.

### Quick Start

```python
from agent_framework_nvidia import NvidiaEmbeddingClient

# Using environment variables (NVIDIA_API_KEY, NVIDIA_EMBEDDING_MODEL)
# Parameters can also be passed directly:
# NvidiaEmbeddingClient(model="nvidia/nemotron-3-embed-1b", api_key="your-api-key")
client = NvidiaEmbeddingClient()

result = await client.get_embeddings(["Hello, world!", "How are you?"])
for embedding in result:
print(f"Dimensions: {embedding.dimensions}")
print(f"Vector: {embedding.vector[:5]}...")

# Close the HTTP client the embedding client created. A client passed as async_client is left open.
await client.close()
```

### Configuration

| Environment Variable | Description |
|---|---|
| `NVIDIA_API_KEY` | Your NVIDIA API key, from [build.nvidia.com](https://build.nvidia.com/) |
| `NVIDIA_EMBEDDING_MODEL` | Embedding model name (e.g., `nvidia/nemotron-3-embed-1b`) |
| `NVIDIA_BASE_URL` | Optional endpoint override, for a self-hosted NIM container |

The service throttles bursts with `429`, which the OpenAI SDK retries twice by default. For heavy
parallel ingestion, pass a pre-configured `async_client`, for example
`AsyncOpenAI(..., max_retries=5)`, to change retries or timeouts.

### Options

`NvidiaEmbeddingOptions` adds two NVIDIA fields to the OpenAI embedding options:

| Option | Values | Purpose |
|---|---|---|
| `input_type` | `"passage"`, `"query"` | Asymmetric retrieval models embed documents and search text differently |
| `truncate` | `"NONE"`, `"START"`, `"END"` | Reject over-long input, or drop tokens from that end |

For retrieval, embed stored documents as passages and search text as queries. Vector collections
forward `embeddings_options` to each request:

```python
await collection.upsert(notes, embeddings_options={"input_type": "passage", "truncate": "END"})
results = await collection.search("How do I call a model?", embeddings_options={"input_type": "query"})
```

`create_vector_search_tool(..., embeddings_options={"input_type": "query"})` does the same for the
tool an agent calls. `nvidia/nemotron-3-embed-1b` accepts only 2048 dimensions, so declare that on
the vector field.

The hosted endpoint accepts at most 256 inputs and a 2 MiB body per request, so the client sends
larger calls, such as an upsert of many records, as consecutive requests within both limits and
returns the vectors in order.

Without `truncate`, the service shortens input over the model's token limit itself, but it rejects any
input over 65,536 characters, and one such document fails the whole call, so nothing in that upsert
is written. Set `truncate="END"` (or `"START"`) when ingesting documents of unknown length.
`truncate="NONE"` rejects input over the token limit instead.

### Choosing a model

Model availability is per-account: the endpoint lists more embedding models than a given API key
is entitled to call, and an unentitled model returns `404 ... Not found for account` rather than a
permission error. Retired models return `410 Gone`. If a model name from the documentation does
not work, list the models available to your key rather than assuming the name is wrong. An invalid key
returns `403 Forbidden` with `Authorization failed`, not `401`.
23 changes: 23 additions & 0 deletions python/packages/nvidia/agent_framework_nvidia/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) Microsoft. All rights reserved.

import importlib.metadata

from ._embedding_client import (
NvidiaEmbeddingClient,
NvidiaEmbeddingOptions,
NvidiaEmbeddingSettings,
RawNvidiaEmbeddingClient,
)

try:
__version__ = importlib.metadata.version(__name__)
except importlib.metadata.PackageNotFoundError:
__version__ = "0.0.0" # Fallback for development mode

__all__ = [
"NvidiaEmbeddingClient",
"NvidiaEmbeddingOptions",
"NvidiaEmbeddingSettings",
"RawNvidiaEmbeddingClient",
"__version__",
]
Loading
Loading