Skip to content

Commit

Permalink
chore (ai/core): move custom provider to stable (#4629)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgrammel authored Jan 31, 2025
1 parent 7be376f commit 08f54fc
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/spotty-suits-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'ai': patch
---

chore (ai/core): move custom provider to stable
12 changes: 6 additions & 6 deletions content/docs/03-ai-sdk-core/40-provider-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ description: Learn how to work with multiple providers

# Provider Management

<Note type="warning">Provider management is an experimental feature.</Note>

When you work with multiple providers and models, it is often desirable to manage them in a central place
and access the models through simple string ids.

Expand All @@ -18,7 +16,7 @@ The provider registry lets you mix **multiple providers** and access them throug

## Custom Providers

You can create a [custom provider](/docs/reference/ai-sdk-core/custom-provider) using `experimental_customProvider`.
You can create a [custom provider](/docs/reference/ai-sdk-core/custom-provider) using `customProvider`.

### Example: custom model settings

Expand All @@ -27,7 +25,7 @@ with pre-configured settings.

```ts
import { openai as originalOpenAI } from '@ai-sdk/openai';
import { experimental_customProvider as customProvider } from 'ai';
import { customProvider } from 'ai';

// custom provider with different model settings:
export const openai = customProvider({
Expand All @@ -49,7 +47,7 @@ You can also provide model name aliases, so you can update the model version in

```ts
import { anthropic as originalAnthropic } from '@ai-sdk/anthropic';
import { experimental_customProvider as customProvider } from 'ai';
import { customProvider } from 'ai';

// custom provider with alias names:
export const anthropic = customProvider({
Expand All @@ -69,7 +67,7 @@ You can limit the available models in the system, even if you have multiple prov
```ts
import { anthropic } from '@ai-sdk/anthropic';
import { openai } from '@ai-sdk/openai';
import { experimental_customProvider as customProvider } from 'ai';
import { customProvider } from 'ai';

export const myProvider = customProvider({
languageModels: {
Expand All @@ -87,6 +85,8 @@ export const myProvider = customProvider({

## Provider Registry

<Note type="warning">The provider registry is an experimental feature.</Note>

You can create a [provider registry](/docs/reference/ai-sdk-core/provider-registry) with multiple providers and models using `experimental_createProviderRegistry`.

### Example: Setup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Registry for managing multiple providers and models (API Reference)

# `createProviderRegistry()`

<Note type="warning">Provider management is an experimental feature.</Note>
<Note type="warning">The provider registry is an experimental feature.</Note>

When you work with multiple providers and models, it is often desirable to manage them
in a central place and access the models through simple string ids.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ description: Custom provider that uses models from a different provider (API Ref

# `customProvider()`

<Note type="warning">Provider management is an experimental feature.</Note>

With a custom provider, you can map ids to any model.
This allows you to set up custom model configurations, alias names, and more.
The custom provider also supports a fallback provider, which is useful for
Expand All @@ -18,7 +16,7 @@ You can create a custom provider using `experiental_createCustomProvider`.

```ts
import { openai } from '@ai-sdk/openai';
import { experimental_customProvider as customProvider } from 'ai';
import { customProvider } from 'ai';

// custom provider with different model settings:
export const myOpenAI = customProvider({
Expand All @@ -34,10 +32,7 @@ export const myOpenAI = customProvider({

## Import

<Snippet
text={`import { experimental_customProvider as customProvider } from "ai"`}
prompt={false}
/>
<Snippet text={`import { customProvider } from "ai"`} prompt={false} />

## API Signature

Expand Down
2 changes: 1 addition & 1 deletion examples/ai-core/src/registry/setup-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { replicate } from '@ai-sdk/replicate';
import { xai } from '@ai-sdk/xai';
import {
experimental_createProviderRegistry as createProviderRegistry,
experimental_customProvider as customProvider,
customProvider,
} from 'ai';
import 'dotenv/config';

Expand Down
21 changes: 10 additions & 11 deletions packages/ai/core/registry/custom-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { NoSuchModelError } from '@ai-sdk/provider';
import { describe, expect, it, vi } from 'vitest';
import { experimental_customProvider } from './custom-provider';

import { MockEmbeddingModelV1 } from '../test/mock-embedding-model-v1';
import { MockImageModelV1 } from '../test/mock-image-model-v1';
import { MockLanguageModelV1 } from '../test/mock-language-model-v1';
import { customProvider } from './custom-provider';

const mockLanguageModel = new MockLanguageModelV1();
const mockEmbeddingModel = new MockEmbeddingModelV1();
Expand All @@ -16,7 +15,7 @@ const mockFallbackProvider = {

describe('languageModel', () => {
it('should return the language model if it exists', () => {
const provider = experimental_customProvider({
const provider = customProvider({
languageModels: { 'test-model': mockLanguageModel },
});

Expand All @@ -26,7 +25,7 @@ describe('languageModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.languageModel.mockReturnValue(mockLanguageModel);

const provider = experimental_customProvider({
const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});

Expand All @@ -37,7 +36,7 @@ describe('languageModel', () => {
});

it('should throw NoSuchModelError if model not found and no fallback', () => {
const provider = experimental_customProvider({});
const provider = customProvider({});
expect(() => provider.languageModel('test-model')).toThrow(
NoSuchModelError,
);
Expand All @@ -46,7 +45,7 @@ describe('languageModel', () => {

describe('textEmbeddingModel', () => {
it('should return the embedding model if it exists', () => {
const provider = experimental_customProvider({
const provider = customProvider({
textEmbeddingModels: { 'test-model': mockEmbeddingModel },
});

Expand All @@ -56,7 +55,7 @@ describe('textEmbeddingModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.textEmbeddingModel.mockReturnValue(mockEmbeddingModel);

const provider = experimental_customProvider({
const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});

Expand All @@ -67,7 +66,7 @@ describe('textEmbeddingModel', () => {
});

it('should throw NoSuchModelError if model not found and no fallback', () => {
const provider = experimental_customProvider({});
const provider = customProvider({});

expect(() => provider.textEmbeddingModel('test-model')).toThrow(
NoSuchModelError,
Expand All @@ -79,7 +78,7 @@ describe('imageModel', () => {
const mockImageModel = new MockImageModelV1();

it('should return the image model if it exists', () => {
const provider = experimental_customProvider({
const provider = customProvider({
imageModels: { 'test-model': mockImageModel },
});

Expand All @@ -89,7 +88,7 @@ describe('imageModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.imageModel = vi.fn().mockReturnValue(mockImageModel);

const provider = experimental_customProvider({
const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});

Expand All @@ -98,7 +97,7 @@ describe('imageModel', () => {
});

it('should throw NoSuchModelError if model not found and no fallback', () => {
const provider = experimental_customProvider({});
const provider = customProvider({});

expect(() => provider.imageModel('test-model')).toThrow(NoSuchModelError);
});
Expand Down
7 changes: 6 additions & 1 deletion packages/ai/core/registry/custom-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { NoSuchModelError } from '@ai-sdk/provider';
*
* @throws {NoSuchModelError} Throws when a requested model is not found and no fallback provider is available.
*/
export function experimental_customProvider<
export function customProvider<
LANGUAGE_MODELS extends Record<string, LanguageModelV1>,
EMBEDDING_MODELS extends Record<string, EmbeddingModelV1<string>>,
IMAGE_MODELS extends Record<string, ImageModelV1>,
Expand Down Expand Up @@ -80,6 +80,11 @@ export function experimental_customProvider<
};
}

/**
* @deprecated Use `customProvider` instead.
*/
export const experimental_customProvider = customProvider;

type ExtractModelId<MODELS extends Record<string, unknown>> = Extract<
keyof MODELS,
string
Expand Down
6 changes: 3 additions & 3 deletions packages/ai/core/registry/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { experimental_customProvider } from './custom-provider';
export * from './no-such-provider-error';
export * from './provider-registry';
export { customProvider, experimental_customProvider } from './custom-provider';
export { NoSuchProviderError } from './no-such-provider-error';
export { experimental_createProviderRegistry } from './provider-registry';

0 comments on commit 08f54fc

Please sign in to comment.