@@ -11,6 +11,7 @@ import { NOVITA_CONFIG } from "../providers/novita";
1111import { REPLICATE_CONFIG } from "../providers/replicate" ;
1212import { SAMBANOVA_CONFIG } from "../providers/sambanova" ;
1313import { TOGETHER_CONFIG } from "../providers/together" ;
14+ import { OPENAI_CONFIG } from "../providers/openai" ;
1415import type { InferenceProvider , InferenceTask , Options , ProviderConfig , RequestArgs } from "../types" ;
1516import { isUrl } from "./isUrl" ;
1617import { version as packageVersion , name as packageName } from "../../package.json" ;
@@ -35,6 +36,7 @@ const providerConfigs: Record<InferenceProvider, ProviderConfig> = {
3536 "fireworks-ai" : FIREWORKS_AI_CONFIG ,
3637 "hf-inference" : HF_INFERENCE_CONFIG ,
3738 hyperbolic : HYPERBOLIC_CONFIG ,
39+ openai : OPENAI_CONFIG ,
3840 nebius : NEBIUS_CONFIG ,
3941 novita : NOVITA_CONFIG ,
4042 replicate : REPLICATE_CONFIG ,
@@ -74,22 +76,38 @@ export async function makeRequestOptions(
7476 if ( ! providerConfig ) {
7577 throw new Error ( `No provider config found for provider ${ provider } ` ) ;
7678 }
79+ if ( providerConfig . clientSideRoutingOnly && ! maybeModel ) {
80+ throw new Error ( `Provider ${ provider } requires a model ID to be passed directly.` ) ;
81+ }
7782 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
7883 const hfModel = maybeModel ?? ( await loadDefaultModel ( task ! ) ) ;
79- const model = await getProviderModelId ( { model : hfModel , provider } , args , {
80- task,
81- chatCompletion,
82- fetch : options ?. fetch ,
83- } ) ;
84+ const model = providerConfig . clientSideRoutingOnly
85+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
86+ removeProviderPrefix ( maybeModel ! , provider )
87+ : // For closed-models API providers, one needs to pass the model ID directly (e.g. "gpt-3.5-turbo")
88+ await getProviderModelId ( { model : hfModel , provider } , args , {
89+ task,
90+ chatCompletion,
91+ fetch : options ?. fetch ,
92+ } ) ;
8493
85- /// If accessToken is passed, it should take precedence over includeCredentials
86- const authMethod = accessToken
87- ? accessToken . startsWith ( "hf_" )
88- ? "hf-token"
89- : "provider-key"
90- : includeCredentials === "include"
91- ? "credentials-include"
92- : "none" ;
94+ const authMethod = ( ( ) => {
95+ if ( providerConfig . clientSideRoutingOnly ) {
96+ // Closed-source providers require an accessToken (cannot be routed).
97+ if ( accessToken && accessToken . startsWith ( "hf_" ) ) {
98+ throw new Error ( `Provider ${ provider } is closed-source and does not support HF tokens.` ) ;
99+ }
100+ return "provider-key" ;
101+ }
102+ if ( accessToken ) {
103+ return accessToken . startsWith ( "hf_" ) ? "hf-token" : "provider-key" ;
104+ }
105+ if ( includeCredentials === "include" ) {
106+ // If accessToken is passed, it should take precedence over includeCredentials
107+ return "credentials-include" ;
108+ }
109+ return "none" ;
110+ } ) ( ) ;
93111
94112 // Make URL
95113 const url = endpointUrl
@@ -178,3 +196,10 @@ async function loadTaskInfo(): Promise<Record<string, { models: { id: string }[]
178196 }
179197 return await res . json ( ) ;
180198}
199+
200+ function removeProviderPrefix ( model : string , provider : string ) : string {
201+ if ( ! model . startsWith ( `${ provider } /` ) ) {
202+ throw new Error ( `Models from ${ provider } must be prefixed by "${ provider } /". Got "${ model } ".` ) ;
203+ }
204+ return model . slice ( provider . length + 1 ) ;
205+ }
0 commit comments