Add OVHcloud AI Endpoints provider (#2238)

Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
This commit is contained in:
Elias
2025-11-28 03:15:50 -05:00
committed by GitHub
parent 5583d92260
commit 09ba5aa43a
15 changed files with 776 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@llamaindex/ovhcloud": major
"@llamaindex/examples": minor
---
Add OVHcloud AI Endpoints provider
@@ -0,0 +1,123 @@
---
title: OVHcloud AI Endpoints
---
OVHcloud AI Endpoints provide OpenAI-compatible embedding models. The service can be used for free with rate limits, or with an API key for higher limits.
OVHcloud is a global player and the leading European cloud provider operating over 450,000 servers within 40 data centers across 4 continents to reach 1.6 million customers in over 140 countries. Our product AI Endpoints offers access to various models with sovereignty, data privacy and GDPR compliance.
You can find the full list of models in the [OVHcloud AI Endpoints catalog](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/).
## Installation
```package-install
npm i llamaindex @llamaindex/ovhcloud
```
## Authentication
OVHcloud AI Endpoints can be used in two ways:
1. **Free tier (with rate limits)**: No API key required. You can omit the `apiKey` parameter or set it to an empty string.
2. **With API key**: For higher rate limits, generate an API key from the [OVHcloud Manager](https://ovh.com/manager) → Public Cloud → AI & Machine Learning → AI Endpoints → API keys.
## Basic Usage
```ts
import { Document, Settings, VectorStoreIndex } from "llamaindex";
import { OVHcloudEmbedding } from "@llamaindex/ovhcloud";
// Update Embed Model (using free tier)
Settings.embedModel = new OVHcloudEmbedding();
// Or with API key from environment variable
import { config } from "dotenv";
config();
Settings.embedModel = new OVHcloudEmbedding({
apiKey: process.env.OVHCLOUD_API_KEY || "",
});
const document = new Document({ text: essay, id_: "essay" });
const index = await VectorStoreIndex.fromDocuments([document]);
const queryEngine = index.asQueryEngine();
const query = "What is the meaning of life?";
const results = await queryEngine.query({
query,
});
```
By default, `OVHcloudEmbedding` uses the `BGE-M3` model. You can change the model by passing the model parameter to the constructor:
```ts
import { OVHcloudEmbedding } from "@llamaindex/ovhcloud";
const model = "text-embedding-3-small";
Settings.embedModel = new OVHcloudEmbedding({
model,
});
```
You can also set the `maxRetries` and `timeout` parameters when initializing `OVHcloudEmbedding` for better control over the request behavior:
```ts
import { Settings } from "llamaindex";
import { OVHcloudEmbedding } from "@llamaindex/ovhcloud";
const model = "text-embedding-3-small";
const maxRetries = 5;
const timeout = 5000; // 5 seconds
Settings.embedModel = new OVHcloudEmbedding({
model,
maxRetries,
timeout,
});
```
## Standalone Usage
```ts
import { OVHcloudEmbedding } from "@llamaindex/ovhcloud";
import { config } from "dotenv";
// For standalone usage, you can optionally configure OVHCLOUD_API_KEY in .env file
config();
const main = async () => {
const model = "BGE-M3";
// Using without API key (free tier)
const embeddings = new OVHcloudEmbedding({ model });
const text = "What is the meaning of life?";
const response = await embeddings.embed([text]);
console.log(response);
};
main();
```
## Base URL
The default base URL is `https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`. You can override it if needed:
```ts
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
additionalSessionOptions: {
baseURL: "https://custom.endpoint.com/v1",
},
});
```
## Resources
- [OVHcloud AI Endpoints Catalog](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/)
- [OVHcloud Manager](https://ovh.com/manager)
- [OVHcloud AI Endpoints Documentation](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/)
## API Reference
- [OVHcloudEmbedding](/typescript/framework-api-reference/classes/ovhcloudembedding/)
@@ -0,0 +1,164 @@
---
title: OVHcloud AI Endpoints
---
OVHcloud AI Endpoints provide serverless access to a variety of pre-trained AI models. The service is OpenAI-compatible and can be used for free with rate limits, or with an API key for higher limits.
OVHcloud is a global player and the leading European cloud provider operating over 450,000 servers within 40 data centers across 4 continents to reach 1.6 million customers in over 140 countries. Our product AI Endpoints offers access to various models with sovereignty, data privacy and GDPR compliance.
You can find the full list of models in the [OVHcloud AI Endpoints catalog](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/).
## Installation
```package-install
npm i llamaindex @llamaindex/ovhcloud
```
## Authentication
OVHcloud AI Endpoints can be used in two ways:
1. **Free tier (with rate limits)**: No API key required. You can omit the `apiKey` parameter or set it to an empty string.
2. **With API key**: For higher rate limits, generate an API key from the [OVHcloud Manager](https://ovh.com/manager) → Public Cloud → AI & Machine Learning → AI Endpoints → API keys.
## Basic Usage
```ts
import { OVHcloudLLM } from "@llamaindex/ovhcloud";
import { Settings } from "llamaindex";
// Using without API key (free tier with rate limits)
Settings.llm = new OVHcloudLLM({
model: "gpt-oss-120b",
});
// Or with API key from environment variable
import { config } from "dotenv";
config();
Settings.llm = new OVHcloudLLM({
model: "gpt-oss-120b",
apiKey: process.env.OVHCLOUD_API_KEY || "",
});
// Or with explicit API key
Settings.llm = new OVHcloudLLM({
model: "gpt-oss-120b",
apiKey: "YOUR_API_KEY",
});
```
You can set the API key via environment variable:
```bash
export OVHCLOUD_API_KEY="<YOUR_API_KEY>"
```
## Load and index documents
For this example, we will use a single document. In a real-world scenario, you would have multiple documents to index.
```ts
import { Document, VectorStoreIndex } from "llamaindex";
const document = new Document({ text: essay, id_: "essay" });
const index = await VectorStoreIndex.fromDocuments([document]);
```
## Query
```ts
const queryEngine = index.asQueryEngine();
const query = "What is the meaning of life?";
const results = await queryEngine.query({
query,
});
```
## Full Example
```ts
import { OVHcloudLLM } from "@llamaindex/ovhcloud";
import { Document, VectorStoreIndex, Settings } from "llamaindex";
// Use custom LLM
const model = "gpt-oss-120b";
Settings.llm = new OVHcloudLLM({ model, temperature: 0 });
async function main() {
const document = new Document({ text: essay, id_: "essay" });
// Load and index documents
const index = await VectorStoreIndex.fromDocuments([document]);
// get retriever
const retriever = index.asRetriever();
// Create a query engine
const queryEngine = index.asQueryEngine({
retriever,
});
const query = "What is the meaning of life?";
// Query
const response = await queryEngine.query({
query,
});
// Log the response
console.log(response.response);
}
```
## Streaming
OVHcloud AI Endpoints supports streaming responses:
```ts
import { OVHcloudLLM } from "@llamaindex/ovhcloud";
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
});
const generator = await llm.chat({
messages: [
{
role: "user",
content: "Tell me about OVHcloud AI Endpoints",
},
],
stream: true,
});
for await (const message of generator) {
process.stdout.write(message.delta);
}
```
## Base URL
The default base URL is `https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`. You can override it if needed:
```ts
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
additionalSessionOptions: {
baseURL: "https://custom.endpoint.com/v1",
},
});
```
## Resources
- [OVHcloud AI Endpoints Catalog](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/)
- [OVHcloud Manager](https://ovh.com/manager)
- [OVHcloud AI Endpoints Documentation](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/)
## API Reference
- [OVHcloudLLM](/typescript/framework-api-reference/classes/ovhcloudllm/)
+50
View File
@@ -0,0 +1,50 @@
import { OVHcloudEmbedding, OVHcloudLLM } from "@llamaindex/ovhcloud";
// OVHcloud AI Endpoints can be used for free with rate limits without an API key
// To use with an API key, set OVHCLOUD_API_KEY environment variable
// or pass it directly in the constructor
// To generate an API key, go to https://ovh.com/manager > Public Cloud > AI & Machine Learning > AI Endpoints > API keys
// Visit our catalog for the list of all available models: https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/
// Example 1: Using without API key (free tier with rate limits)
const ovhcloudFree = new OVHcloudLLM({
model: "gpt-oss-120b",
// apiKey is optional - can be omitted or set to empty string for free tier
});
// Example 2: Using with API key
const ovhcloud = new OVHcloudLLM({
model: "gpt-oss-120b",
apiKey: process.env.OVHCLOUD_API_KEY || "",
});
(async () => {
console.log("Chatting with OVHcloud AI Endpoints...");
const generator = await ovhcloud.chat({
messages: [
{
role: "system",
content: "You are a helpful AI assistant.",
},
{
role: "user",
content: "Tell me about OVHcloud AI Endpoints",
},
],
stream: true,
});
for await (const message of generator) {
process.stdout.write(message.delta);
}
console.log("\n");
// Example with embeddings
console.log("Getting embeddings...");
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
});
const vector = await embedding.getTextEmbedding("Hello world!");
console.log("Vector dimensions:", vector.length);
console.log("First 5 values:", vector.slice(0, 5));
})();
+1
View File
@@ -40,6 +40,7 @@
"@llamaindex/notion": "^0.1.21",
"@llamaindex/ollama": "^0.1.23",
"@llamaindex/openai": "^0.4.21",
"@llamaindex/ovhcloud": "^0.0.1",
"@llamaindex/perplexity": "^0.0.34",
"@llamaindex/pinecone": "^0.1.22",
"@llamaindex/portkey-ai": "^0.0.64",
+7
View File
@@ -0,0 +1,7 @@
# @llamaindex/ovhcloud
## 0.0.1
### Patch Changes
- Initial release of OVHcloud AI Endpoints provider
+130
View File
@@ -0,0 +1,130 @@
# CLAUDE.md - OVHcloud AI Endpoints Provider Package
This package provides LLM and embedding integrations for OVHcloud AI Endpoints in LlamaIndex.TS.
## Package Overview
The `@llamaindex/ovhcloud` package offers two main components:
1. **OVHcloudLLM** - OpenAI-compatible chat model interface using OVHcloud's hosted models
2. **OVHcloudEmbedding** - OpenAI-compatible embedding API integration for text embeddings
## Architecture
### LLM Integration (src/llm.ts)
The `OVHcloudLLM` class extends the OpenAI class from `@llamaindex/openai`, leveraging OVHcloud's OpenAI-compatible API:
- **Base URL**: `https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`
- **Default Model**: `gpt-oss-120b`
- **Authentication**: Optional - can use free tier with rate limits (empty API key) or with `OVHCLOUD_API_KEY` environment variable
- **Implementation**: Wrapper around OpenAI class with OVHcloud-specific defaults
### Embedding Integration (src/embedding.ts)
The `OVHcloudEmbedding` class extends the `OpenAIEmbedding` class:
- **Base URL**: `https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`
- **Default Model**: `BGE-M3`
- **Authentication**: Optional - can use free tier with rate limits (empty API key) or with `OVHCLOUD_API_KEY` environment variable
- **Implementation**: Wrapper around OpenAIEmbedding class with OVHcloud-specific defaults
## Configuration
### Environment Variables
- `OVHCLOUD_API_KEY` - Optional API key. If not provided or empty, uses free tier with rate limits
### LLM Configuration
```typescript
import { OVHcloudLLM } from "@llamaindex/ovhcloud";
// Free tier (no API key required)
const llm = new OVHcloudLLM({
model: "gpt-oss-120b", // optional
// apiKey omitted or empty string for free tier
});
// With API key
const llm = new OVHcloudLLM({
model: "gpt-oss-120b", // optional
apiKey: "your-api-key", // optional if OVHCLOUD_API_KEY is set
// ... other OpenAI-compatible options
});
```
### Embedding Configuration
```typescript
import { OVHcloudEmbedding } from "@llamaindex/ovhcloud";
// Free tier (no API key required)
const embedding = new OVHcloudEmbedding({
model: "BGE-M3", // optional
// apiKey omitted or empty string for free tier
});
// With API key
const embedding = new OVHcloudEmbedding({
model: "BGE-M3", // optional
apiKey: "your-api-key", // optional if OVHCLOUD_API_KEY is set
// ... other OpenAI-compatible options
});
```
## Key Features
### LLM Features
- Full OpenAI API compatibility through inheritance
- Optional API key management (supports free tier with rate limits)
- Support for all OVHcloud hosted models
- Default base URL configured for OVHcloud endpoints
### Embedding Features
- Full OpenAI API compatibility through inheritance
- Optional API key management (supports free tier with rate limits)
- Support for OpenAI-compatible embedding models
- Default base URL configured for OVHcloud endpoints
## Free Tier Support
OVHcloud AI Endpoints can be used for free with rate limits by:
- Omitting the `apiKey` parameter
- Setting `apiKey` to an empty string
- Not setting the `OVHCLOUD_API_KEY` environment variable
For higher rate limits, generate an API key from:
- OVHcloud Manager: https://ovh.com/manager
- Navigate to: Public Cloud → AI & Machine Learning → AI Endpoints → API keys
## Dependencies
- `@llamaindex/core` - Core interfaces and utilities
- `@llamaindex/env` - Environment variable handling
- `@llamaindex/openai` - OpenAI implementation (for both LLM and embedding)
## Development
- **Build**: `pnpm build` (uses bunchee)
- **Watch**: `pnpm dev` (uses bunchee --watch)
- **Test**: `pnpm test` (uses vitest)
- **Output**: Dual CJS/ESM exports in `dist/`
## API Endpoints
- **Base URL**: `https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`
- **Catalog**: https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/
- **Documentation**: https://www.ovhcloud.com/en/public-cloud/ai-endpoints/
## Resources
- [OVHcloud AI Endpoints Catalog](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog/)
- [OVHcloud Manager](https://ovh.com/manager)
- [OVHcloud AI Endpoints Documentation](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/)
This package follows the LlamaIndex.TS provider pattern, implementing standard interfaces while providing OVHcloud-specific configuration and free tier support.
+46
View File
@@ -0,0 +1,46 @@
{
"name": "@llamaindex/ovhcloud",
"description": "OVHcloud AI Endpoints Adapter for LlamaIndex",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
}
},
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/run-llama/LlamaIndexTS.git",
"directory": "packages/providers/ovhcloud"
},
"scripts": {
"build": "bunchee",
"dev": "bunchee --watch",
"test": "vitest run"
},
"dependencies": {
"@llamaindex/env": "workspace:*",
"@llamaindex/openai": "workspace:*"
},
"devDependencies": {
"vitest": "^2.1.5",
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*"
},
"peerDependencies": {
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*"
}
}
@@ -0,0 +1,27 @@
import { getEnv } from "@llamaindex/env";
import { OpenAIEmbedding } from "@llamaindex/openai";
import { BASE_URL, ENV_VARIABLE_NAME } from "./utils";
export class OVHcloudEmbedding extends OpenAIEmbedding {
constructor(init?: Omit<Partial<OpenAIEmbedding>, "session">) {
const {
apiKey = getEnv(ENV_VARIABLE_NAME) ?? "",
additionalSessionOptions = {},
model = "BGE-M3",
...rest
} = init ?? {};
// OVHcloud allows empty API key for free tier with rate limits
// So we don't throw an error if apiKey is empty or undefined
additionalSessionOptions.baseURL =
additionalSessionOptions.baseURL ?? BASE_URL;
super({
apiKey: apiKey || "", // Use empty string if not provided
additionalSessionOptions,
model,
...rest,
});
}
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./embedding";
export * from "./llm";
+35
View File
@@ -0,0 +1,35 @@
import { getEnv } from "@llamaindex/env";
import { OpenAI } from "@llamaindex/openai";
import { BASE_URL, ENV_VARIABLE_NAME } from "./utils";
export class OVHcloudLLM extends OpenAI {
constructor(init?: Omit<Partial<OpenAI>, "session">) {
const {
apiKey = getEnv(ENV_VARIABLE_NAME) ?? "",
additionalSessionOptions = {},
model = "gpt-oss-120b",
...rest
} = init ?? {};
// OVHcloud allows empty API key for free tier with rate limits
// So we don't throw an error if apiKey is empty or undefined
additionalSessionOptions.baseURL =
additionalSessionOptions.baseURL ?? BASE_URL;
super({
apiKey: apiKey || "", // Use empty string if not provided
additionalSessionOptions,
model,
...rest,
});
}
}
/**
* Convenience function to create a new OVHcloudLLM instance.
* @param init - Optional initialization parameters for the OVHcloudLLM instance.
* @returns A new OVHcloudLLM instance.
*/
export const ovhcloud = (init?: ConstructorParameters<typeof OVHcloudLLM>[0]) =>
new OVHcloudLLM(init);
+2
View File
@@ -0,0 +1,2 @@
export const ENV_VARIABLE_NAME = "OVHCLOUD_API_KEY";
export const BASE_URL = "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1";
@@ -0,0 +1,145 @@
import type { ChatMessage } from "@llamaindex/core/llms";
import { setEnvs } from "@llamaindex/env";
import { describe, expect, test } from "vitest";
import { OVHcloudEmbedding, OVHcloudLLM } from "../src/index";
import { BASE_URL } from "../src/utils";
describe("OVHcloudLLM", () => {
describe("Initialization", () => {
test("should initialize without API key (free tier)", () => {
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
});
expect(llm).toBeInstanceOf(OVHcloudLLM);
expect(llm.model).toBe("gpt-oss-120b");
});
test("should initialize with empty API key (free tier)", () => {
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
apiKey: "",
});
expect(llm).toBeInstanceOf(OVHcloudLLM);
});
test("should initialize with API key from environment", () => {
setEnvs({
OVHCLOUD_API_KEY: "test-api-key",
});
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
});
expect(llm).toBeInstanceOf(OVHcloudLLM);
});
test("should initialize with explicit API key", () => {
const llm = new OVHcloudLLM({
model: "gpt-oss-120b",
apiKey: "explicit-api-key",
});
expect(llm).toBeInstanceOf(OVHcloudLLM);
});
test("should use default model if not specified", () => {
const llm = new OVHcloudLLM();
expect(llm.model).toBe("gpt-oss-120b");
});
test("should use custom base URL if provided", () => {
const customBaseURL = "https://custom.endpoint.com/v1";
const llm = new OVHcloudLLM({
additionalSessionOptions: {
baseURL: customBaseURL,
},
});
expect(llm.additionalSessionOptions?.baseURL).toBe(customBaseURL);
});
});
describe("Base URL Configuration", () => {
test("should use default OVHcloud base URL", () => {
const llm = new OVHcloudLLM();
expect(llm.additionalSessionOptions?.baseURL).toBe(BASE_URL);
});
});
describe("Message Formatting", () => {
test("should format basic messages correctly", () => {
const llm = new OVHcloudLLM();
const inputMessages: ChatMessage[] = [
{
content: "You are a helpful assistant.",
role: "system",
},
{
content: "Hello?",
role: "user",
},
];
// OVHcloudLLM extends OpenAI, so it uses OpenAI's message formatting
// We just verify the instance is created correctly
expect(llm).toBeInstanceOf(OVHcloudLLM);
});
});
});
describe("OVHcloudEmbedding", () => {
describe("Initialization", () => {
test("should initialize without API key (free tier)", () => {
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
});
expect(embedding).toBeInstanceOf(OVHcloudEmbedding);
expect(embedding.model).toBe("BGE-M3");
});
test("should initialize with empty API key (free tier)", () => {
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
apiKey: "",
});
expect(embedding).toBeInstanceOf(OVHcloudEmbedding);
});
test("should initialize with API key from environment", () => {
setEnvs({
OVHCLOUD_API_KEY: "test-api-key",
});
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
});
expect(embedding).toBeInstanceOf(OVHcloudEmbedding);
});
test("should initialize with explicit API key", () => {
const embedding = new OVHcloudEmbedding({
model: "BGE-M3",
apiKey: "explicit-api-key",
});
expect(embedding).toBeInstanceOf(OVHcloudEmbedding);
});
test("should use default model if not specified", () => {
const embedding = new OVHcloudEmbedding();
expect(embedding.model).toBe("BGE-M3");
});
test("should use custom base URL if provided", () => {
const customBaseURL = "https://custom.endpoint.com/v1";
const embedding = new OVHcloudEmbedding({
additionalSessionOptions: {
baseURL: customBaseURL,
},
});
expect(embedding.additionalSessionOptions?.baseURL).toBe(customBaseURL);
});
});
describe("Base URL Configuration", () => {
test("should use default OVHcloud base URL", () => {
const embedding = new OVHcloudEmbedding();
expect(embedding.additionalSessionOptions?.baseURL).toBe(BASE_URL);
});
});
});
+19
View File
@@ -0,0 +1,19 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./lib",
"tsBuildInfoFile": "./lib/.tsbuildinfo"
},
"include": ["./src"],
"references": [
{
"path": "../openai/tsconfig.json"
},
{
"path": "../../env/tsconfig.json"
}
]
}
+19
View File
@@ -438,6 +438,9 @@ importers:
'@llamaindex/openai':
specifier: ^0.4.21
version: link:../packages/providers/openai
'@llamaindex/ovhcloud':
specifier: ^0.0.1
version: link:../packages/providers/ovhcloud
'@llamaindex/perplexity':
specifier: ^0.0.34
version: link:../packages/providers/perplexity
@@ -1167,6 +1170,22 @@ importers:
specifier: ^4.1.5
version: 4.1.5
packages/providers/ovhcloud:
dependencies:
'@llamaindex/env':
specifier: workspace:*
version: link:../../env
'@llamaindex/openai':
specifier: workspace:*
version: link:../openai
devDependencies:
'@llamaindex/core':
specifier: workspace:*
version: link:../../core
vitest:
specifier: ^2.1.5
version: 2.1.9(@edge-runtime/vm@5.0.0)(@types/node@24.0.13)(happy-dom@17.4.4)(lightningcss@1.29.3)(msw@2.7.4(@types/node@24.0.13)(typescript@5.9.2))(terser@5.39.0)
packages/providers/perplexity:
dependencies:
'@llamaindex/openai':