-
Notifications
You must be signed in to change notification settings - Fork 29
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
Azure OpenAI API #3
Comments
Thanks @didalgolab. It's not in my near future plans, maybe in the next major release, however I would like to know why you think I should support it? I mean, wouldn't it be kind of redundant to support Azure OpenAI if they are calling OpenAI services behind the scenes? |
One reason to use Azure OpenAI is that currently it's one of the few methods available for accessing gpt-4-32k model. Other considerations that might be important for some users or companies include: usage policies, GDPR compliance, co-location with other Azure services. |
@didalgolab did you try it with Azure OpenAI? It may just work. I tried it with Anyscale and it works like a charm including function calling. |
@the-gigi Yes, and unfortunately, it's not compatible. While the Anyscale API has been built with compatibility in mind, Azure OpenAI hasn't. It seems almost as if Microsoft did this on purpose:
But anyway, it's a low priority for me now. |
OK. I actually need to access Azure OpenAI now, so I'll look into making |
@sashirestela I looked into it and I think with some modifications simple-openai can handle Azure OpenAI too. I'm willing to work on a PR with your guidance. Here are the sticking points:
Azure OpenAI has a dedicated URL per deployment. A deployment already has a specific model configured. The format of the URL is:
So, from simple-openai point of view the base URL will be https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME (note, no /v1) and then it needs in the end to add the query params. This can be accomplished by checking if the base url contains ? and then strip these and in the end before sending the actual HTTP request append the query params back. simple-openai uses cleverclient, which provides an abstraction over URLs with annotations. so, I'm not sure how to accomplish it exactly. I see that for GET requests there is a @query annotation. maybe it work for POST requests too. The other related issue is that simple-openai automatically adds the /v1 before each endpoint. This can be handled simply by removing it and having the endpoint be just /chat/completions (for chat, similar to other endpoints) instead of :
just:
Two additional minor issues as @didalgolab pointed out:
I believe supporting Azure OpenAI can be done without making simple-openai aware of the differences between providers. But, if going for multi-provider support it may be better to introduce the concept of an optional provider. The default will be OpenAI (which works out of the box for Anyscale too). For other providers like Azure OpenAI that currently are incompatible with some assumptions, simple-openai can internally adjust its behavior (e.g. drop the /v1 only for Azure OpenAI and add the Let me know what you think. |
@the-gigi @didalgolab Do you know if the api-version url parameter can be different by endpoint or is it unique for all the API? |
@sashirestela yes. they can even be different for the same endpoint. Each endpoint corresponds to a Deployment, which has its own model and has its own subdomain and supports different API versions with the query parameter. See https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning |
In that case, one option could be adding a Query parameter to all the http methods and doing one of the following:
Let me try to think of other options, but if you say that the parameter could change in every call, it is a very challenging requirement. |
@sashir my thinking is that simple-openai should support the latest version by default for each API method. so, users normally don't have to pass it. But, if they want a different API version then there will be an optional apiVersion in their request and it will replace the default when specified. All this applies only if its targeting Azure OPenAI of course. |
The scenario is the same, because Java doesn't support optional arguments for methods neither default values for arguments, so we will need to overload all the http methods with new default methods in order to support that requirement of variable api-version for Azure. The code of the OpenAI.java interface is going to grow a lot just for that new parameter. I think that trying to use the same interface is very hard. Perhaps another option could be to create duplicated versions, I know that it is not ideal for your goal, but Microsoft is imposing a non standard way to handle this:
EDIT:
A remaining issue is how to handle the mandatory field model in the domain request objects. Maybe we will need to duplicate those Java classes also. What do you think? |
My idea is not to pass the query parameters as part of the method, but as part of the request object. so, for example ChatRequest will have one new nullable field
If the field is not present then the default apiVersion for each Azure OpenAI API endpoint is appended to the URL. So, the method signature remains (except for the /v1 that will be added to OpenAI only, or the relevant version if not /v1):
We will have
It will require some dynamic setting of the base URL before calling celverclient. The @resource annotation specifies just part of the path part of the URL. Different API methods and providers may have different prefixes (e.g. /v1 in case of OpenAI for /chat/completions) and different query params (api-version in case of Azure OpenAI) Regarding the model. it shouldn't be required if we go for the multi-provider approach because not all providers require it. We can still implement per-provider logic and verify that for OpenAI it is provided. |
If you pass it as part of the request object, it'll be on the payload body of the request, not in the url as a query parameter, so have you verified that Azure is going to recognize it in that way?
Remember that you need to do this by method (/v1 could be different by method). If you change baseUrl you will change it for all the methods and in a multithread scenario this could be an issue.
If we are going to support per-provider logic, please, take in account the Open-Close principle: open for extension and closed for modifications. |
Yes. There is a lot of stuff that happens automatically with the annotations and serialization, so I need to verify my idea works. I'll follow up after I tried to implement my approach. It will require some provider-specific logic for sure. I hope it doesn't require duplicating a lot of classes and interfaces with different signatures per provider. Instead, I aim for a general-purpose implementation with some per-provider map of method -> prefix + query params. But, until I actually implement it, it is speculation only. |
In my opinion The user will have to create separate clients with different baseUrls for different endpoints anyway. I also agree with @sashirestela to add separate interface |
Technically the base URL is the part of the URL before the the path. This is how it is treated also by simple-openai/cleverclient. cleverclient constructs the full URL by appending the Path (e.g. /v1/chat/completions) to the base Url. It also checks if there are query params defined in the method signature and adds those. What we need is to provide the queryParams dynamically to clever client, so it can construct the URL as usual and then in the end add the provided query params (if any). This is where it happens: @sashirestela the current design of cleverclient hard-codes the query params in the interface annotations as in:
If you prefer to keep it strict (all query params must be specified at the interface level) then I think supporting Azure OpenAI will require a split. But, if we add dynamic query params to cleverclient then simple-openai can add api-version query param based on the provider and we can remain with one version of the interfaces. |
@sashirestela See sashirestela/cleverclient#39. This PR will allow simple-openai to inject the Azure OpenAI api-version query parameter into cleverclient without touching the interfaces. |
@the-gigi Many things to comment:
|
I've just developed the new feature UrlInterceptor. You can see an example of usage in the main branch (it is not deployed to Maven Central yet): In that example, I'm creating a functional Function with a logic to add a query param to url and remove '/vN' from url. Then, it is passed to the Cleverclient builder and it'll be executed automatically every time that we call a http method and it'll modify the url before hitting the server. On the other hand, in previous comments you said:
So, where in the code do you think that we could introduce a per-provider logic to validate if the model in the request objects are required or not? EDIT: |
@sashirestela that looks great. I didn't verify if it's OK to send a redundant model. I wonder if cleverclient should provide just a url interceptor or a complete request interceptor. This way consumers can intercept and modify any part of the request, including the body, which can be used to remove the model if necessary. |
Guys, the cleverclient library was extended to handle the full request (url, body, headers). So, simple-openai can now support to use Azure OpenAI, and you just need to provide a See an example of a requestInterceptor here: https://github.com/sashirestela/cleverclient/blob/main/src/test/java/io/github/sashirestela/cleverclient/CleverClientTest.java#L71-L139 |
Nice project! Do you plan to support the Azure OpenAI API? https://learn.microsoft.com/en-us/azure/ai-services/openai/reference
The text was updated successfully, but these errors were encountered: