-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Inference] Move provider-specific logic away from makeRequestOptions
(1 provider == 1 module)
#1208
base: main
Are you sure you want to change the base?
Conversation
export const replicateConfig: ProviderConfig = { | ||
baseUrl: REPLICATE_API_BASE_URL, | ||
makeBody, | ||
makeHeaders, | ||
makeUrl, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if a class with static method would be more idiomatic - wdyt @coyotte508 @julien-c ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an example, here is how a class would look like (transcribed using hf.co/chat). In Python I usually tend to avoid static methods as it's more boilerplate and usually don't benefit from being a class. But happy to change if it's more idiomatic in JS!
export abstract class ProviderConfig {
static baseUrl: string;
static makeBody(params: BodyParams): unknown {
throw new Error("Not implemented");
}
static makeHeaders(params: HeaderParams): Record<string, string> {
throw new Error("Not implemented");
}
static makeUrl(params: UrlParams): string {
throw new Error("Not implemented");
}
}
(...)
export class ReplicateConfig extends ProviderConfig {
static baseUrl = "https://api.replicate.com";
static makeBody({ args, model }: BodyParams): unknown {
return {
input: args,
version: model.includes(":") ? model.split(":")[1] : undefined,
};
}
static makeHeaders({ accessToken }: HeaderParams): Record<string, string> {
return {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
Prefer: "Wait",
};
}
static makeUrl({ baseUrl, model }: UrlParams): string {
if (model.includes(":")) {
return `${baseUrl}/v1/predictions`;
}
return `${baseUrl}/v1/models/${model}/predictions`;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that in huggingface_hub
we use classes because we decided to go with "1 class == 1 provider<>task pair" and we benefit from inheritance (example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it!!
I think using classes instead of interfaces might be slightly more idiomatic - would love opinion from @coyotte508 and @julien-c
makeRequestOptions
(1 provider == 1 module)
I completed all the providers. Now There is still a topic around the data structure to adopt (interface vs class with static methods - see #1208 (comment)). Happy to adapt once agreed on it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I have a few code style suggestions.
Subsequently to this PR, I thinl we should also factor task-specific logic within the provider modules.
// Make body | ||
const body = binary | ||
? args.data | ||
: JSON.stringify( | ||
providerConfig.makeBody({ | ||
args: remainingArgs as Record<string, unknown>, | ||
model, | ||
taskHint, | ||
chatCompletion, | ||
}) | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Independent from the changes introduced here: I dislike this binary data special case, it's not obvious from an external pov that passing data
in arguments will result in the payload being passed as raw bytes in the body.
(addressed the code style comments, thanks for the advice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Would love to have another review from @coyotte508 and/or @julien-c
Goal of this PR is to move away any provider-specific logic from
makeRequestOptions.ts
. In theory no tests should be updated as we only want to modify the internal logic without modifying input/output behavior.Feedback around structure, TS convention, naming, etc. is welcome.
How it works ?
Each provider must define a
providerConfig
consisting of:(with
HeaderParams
,UrlParams
,BodyParams
the parameters required to build these)