Skip to content

Commit b53b93e

Browse files
AVthekinggr2m
authored andcommitted
feat(provider/google & provider/anthropic): support for custom provider name for anthropic and google (#10091)
## Background With the baseURL of createAnthropic and createGoogleGenerativeAI, we can use some providers that offer Anthropic or Gemini-compatible APIs. Therefore, we hope to pass in a custom provider name to make it easier to identify specific providers in logging and error tracking. ## Summary Added support for custom provider name in google and anthropic ## Manual Verification Wrote eg with telemetery for both google and anthropic to test the custom provider names ## Related Issues Fixes #9911 Co-authored-by: Gregor Martynus <[email protected]>
1 parent 1571ecd commit b53b93e

File tree

7 files changed

+164
-4
lines changed

7 files changed

+164
-4
lines changed

.changeset/hot-onions-reply.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@ai-sdk/anthropic': patch
3+
'@ai-sdk/google': patch
4+
---
5+
6+
Support for custom provider name in google and anthropic providers
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { createAnthropic } from '@ai-sdk/anthropic';
2+
import { generateText } from 'ai';
3+
import 'dotenv/config';
4+
5+
import { NodeSDK } from '@opentelemetry/sdk-node';
6+
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
7+
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
8+
9+
const sdk = new NodeSDK({
10+
traceExporter: new ConsoleSpanExporter(),
11+
instrumentations: [getNodeAutoInstrumentations()],
12+
});
13+
14+
sdk.start();
15+
16+
async function main() {
17+
const myCustomProvider = createAnthropic({
18+
name: 'my-anthropic-proxy',
19+
});
20+
21+
await generateText({
22+
model: myCustomProvider('claude-sonnet-4-20250514'),
23+
prompt: 'Say hello in 5 words',
24+
experimental_telemetry: {
25+
isEnabled: true,
26+
functionId: 'anthropic-custom-provider-demo',
27+
metadata: {
28+
environment: 'demo',
29+
endpoint_type: 'my-anthropic-proxy',
30+
cost_tracking: 'enabled',
31+
},
32+
},
33+
});
34+
35+
await sdk.shutdown();
36+
}
37+
38+
main().catch(console.error);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { createGoogleGenerativeAI } from '@ai-sdk/google';
2+
import { generateText } from 'ai';
3+
import 'dotenv/config';
4+
5+
import { NodeSDK } from '@opentelemetry/sdk-node';
6+
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
7+
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
8+
9+
const sdk = new NodeSDK({
10+
traceExporter: new ConsoleSpanExporter(),
11+
instrumentations: [getNodeAutoInstrumentations()],
12+
});
13+
14+
sdk.start();
15+
16+
async function main() {
17+
const myCustomProvider = createGoogleGenerativeAI({
18+
name: 'my-custom-provider',
19+
});
20+
21+
await generateText({
22+
model: myCustomProvider('gemini-2.5-flash'),
23+
prompt: 'Say hello in 5 words',
24+
experimental_telemetry: {
25+
isEnabled: true,
26+
functionId: 'custom-provider-demo',
27+
metadata: {
28+
environment: 'demo',
29+
customer_id: 'demo-user',
30+
request_source: 'example',
31+
},
32+
},
33+
});
34+
35+
await sdk.shutdown();
36+
}
37+
38+
main().catch(console.error);

packages/anthropic/src/anthropic-provider.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,28 @@ describe('createAnthropic', () => {
103103
});
104104
});
105105
});
106+
107+
describe('anthropic provider - custom provider name', () => {
108+
beforeEach(() => {
109+
vi.clearAllMocks();
110+
});
111+
112+
it('should use custom provider name when specified', () => {
113+
const provider = createAnthropic({
114+
name: 'my-claude-proxy',
115+
apiKey: 'test-api-key',
116+
});
117+
118+
const model = provider('claude-3-haiku-20240307');
119+
expect(model.provider).toBe('my-claude-proxy');
120+
});
121+
122+
it('should default to anthropic.messages when name not specified', () => {
123+
const provider = createAnthropic({
124+
apiKey: 'test-api-key',
125+
});
126+
127+
const model = provider('claude-3-haiku-20240307');
128+
expect(model.provider).toBe('anthropic.messages');
129+
});
130+
});

packages/anthropic/src/anthropic-provider.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ or to provide a custom fetch implementation for e.g. testing.
6262
fetch?: FetchFunction;
6363

6464
generateId?: () => string;
65+
66+
/**
67+
* Custom provider name
68+
* Defaults to 'anthropic.messages'.
69+
*/
70+
name?: string;
6571
}
6672

6773
/**
@@ -78,6 +84,8 @@ export function createAnthropic(
7884
}),
7985
) ?? 'https://api.anthropic.com/v1';
8086

87+
const providerName = options.name ?? 'anthropic.messages';
88+
8189
const getHeaders = () =>
8290
withUserAgentSuffix(
8391
{
@@ -94,7 +102,7 @@ export function createAnthropic(
94102

95103
const createChatModel = (modelId: AnthropicMessagesModelId) =>
96104
new AnthropicMessagesLanguageModel(modelId, {
97-
provider: 'anthropic.messages',
105+
provider: providerName,
98106
baseURL,
99107
headers: getHeaders,
100108
fetch: options.fetch,

packages/google/src/google-provider.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,40 @@ describe('google-provider', () => {
268268
`);
269269
});
270270
});
271+
272+
describe('google provider - custom provider name', () => {
273+
beforeEach(() => {
274+
vi.clearAllMocks();
275+
});
276+
277+
it('should use custom provider name when specified', () => {
278+
const provider = createGoogleGenerativeAI({
279+
name: 'my-gemini-proxy',
280+
apiKey: 'test-api-key',
281+
});
282+
283+
provider('gemini-pro');
284+
285+
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
286+
'gemini-pro',
287+
expect.objectContaining({
288+
provider: 'my-gemini-proxy',
289+
}),
290+
);
291+
});
292+
293+
it('should default to google.generative-ai when name not specified', () => {
294+
const provider = createGoogleGenerativeAI({
295+
apiKey: 'test-api-key',
296+
});
297+
298+
provider('gemini-pro');
299+
300+
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
301+
'gemini-pro',
302+
expect.objectContaining({
303+
provider: 'google.generative-ai',
304+
}),
305+
);
306+
});
307+
});

packages/google/src/google-provider.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ or to provide a custom fetch implementation for e.g. testing.
9090
Optional function to generate a unique ID for each request.
9191
*/
9292
generateId?: () => string;
93+
94+
/**
95+
* Custom provider name
96+
* Defaults to 'google.generative-ai'.
97+
*/
98+
name?: string;
9399
}
94100

95101
/**
@@ -102,6 +108,8 @@ export function createGoogleGenerativeAI(
102108
withoutTrailingSlash(options.baseURL) ??
103109
'https://generativelanguage.googleapis.com/v1beta';
104110

111+
const providerName = options.name ?? 'google.generative-ai';
112+
105113
const getHeaders = () =>
106114
withUserAgentSuffix(
107115
{
@@ -117,7 +125,7 @@ export function createGoogleGenerativeAI(
117125

118126
const createChatModel = (modelId: GoogleGenerativeAIModelId) =>
119127
new GoogleGenerativeAILanguageModel(modelId, {
120-
provider: 'google.generative-ai',
128+
provider: providerName,
121129
baseURL,
122130
headers: getHeaders,
123131
generateId: options.generateId ?? generateId,
@@ -138,7 +146,7 @@ export function createGoogleGenerativeAI(
138146

139147
const createEmbeddingModel = (modelId: GoogleGenerativeAIEmbeddingModelId) =>
140148
new GoogleGenerativeAIEmbeddingModel(modelId, {
141-
provider: 'google.generative-ai',
149+
provider: providerName,
142150
baseURL,
143151
headers: getHeaders,
144152
fetch: options.fetch,
@@ -149,7 +157,7 @@ export function createGoogleGenerativeAI(
149157
settings: GoogleGenerativeAIImageSettings = {},
150158
) =>
151159
new GoogleGenerativeAIImageModel(modelId, settings, {
152-
provider: 'google.generative-ai',
160+
provider: providerName,
153161
baseURL,
154162
headers: getHeaders,
155163
fetch: options.fetch,

0 commit comments

Comments
 (0)