Skip to content
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

feat: Integrate Azure OpenAI API. #402

Closed
wants to merge 11 commits into from

Conversation

L4zyy
Copy link

@L4zyy L4zyy commented Dec 7, 2023

Description

This PR integrate the Azure OpenAI API to CAMEL.

Motivation and Context

Integrate Azure OpenAI API, close #231

  • I have raised an issue to propose this change (required for new features and bug fixes)

Types of changes

What types of changes does your code introduce? Put an x in all the boxes that apply:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds core functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (update in the documentation)
  • Example (update in the folder of example)

Implemented Tasks

  • Add Azure OpenAI model.
  • Add Azure OpenAI model tests.
  • Run though role playing example using Azure OpenAI API.

Checklist

Go over all the following points, and put an x in all the boxes that apply.
If you are unsure about any of these, don't hesitate to ask. We are here to help!

  • I have read the CONTRIBUTION guide. (required)
  • My change requires a change to the documentation.
  • I have updated the tests accordingly. (required for a bug fix or a new feature)
  • I have updated the documentation accordingly.

@lightaime lightaime added the Model Related to backend models label Dec 8, 2023
@L4zyy L4zyy force-pushed the feature/azure-openai-api branch 2 times, most recently from 92fbe8e to 871b506 Compare December 9, 2023 09:56
@L4zyy
Copy link
Author

L4zyy commented Dec 9, 2023

Hi, @lightaime, I've checked all the failed tests and nearly all of them are "openai.APIConnectionError: Connection error.". I found a comment in this MR may related to my problem. I run some of the failed tests locally and all of them are passed. Could you help me with this?

There are also two other failed test.

  • "Failed: OPENWEATHERMAP_API_KEY environment variable is not set.", Is this fail with the same reason?
  • "openai.OpenAIError: Missing credentials. Please pass one of api_key, azure_ad_token, azure_ad_token_provider, or the AZURE_OPENAI_API_KEY or AZURE_OPENAI_AD_TOKEN environment variables.". This test failed since my MR needs new environment variables to run with Azure OpenAI API(I update the README about this). Is there any way to update environment variables when testing?

Copy link
Member

@lightaime lightaime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @L4zyy for the PR! Overall looks good. I have some questions

  • About the AzureOpenAIModel, do we need a seperate class for azure openai models? It seems the only differences between AzureOpenAIModel and OpenAIModel will be the creation of self._client. Should we just support azure models with OpenAIModel?
  • Should we just introduce enums in https://github.com/camel-ai/camel/blob/master/camel/types/enums.py to support the client creation? We can introduce somethings like: ModelType.Azure_GPT_3_5_TURBO and so on.

@dandansamax @Wendong-Fan any suggesitions?

Comment on lines 25 to 30
azure_model_name_to_type = {
"gpt-35-turbo": ModelType.GPT_3_5_TURBO,
"gpt-35-turbo-16k": ModelType.GPT_3_5_TURBO_16K,
"gpt-4": ModelType.GPT_4,
"gpt-4-32k": ModelType.GPT_4_32K,
"gpt-4-1106-preview": ModelType.GPT_4_TURBO,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code for an older implementation, will be remove in the next commit.

assert self.deployment_name is not None, \
"Azure model deployment name is not provided."

self.model_name = os.environ.get('AZURE_MODEL_TOKEN_LIMIT', 8192)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it called model_name?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologize for this typo, will be correct in the next commit.

Comment on lines 59 to 60
self.deployment_name = os.environ.get('AZURE_MODEL_DEPLOYMENT_NAME',
'gpt-3.5-turbo-1106')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need self.deployment_name? Could we just use self.model_type.value?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is explained in the comment below. I will try to find a better way to do it.

Comment on lines 52 to 56
use_azure_api = 'USE_AZURE_API' in os.environ
if use_azure_api:
model_class = AzureOpenAIModel
else:
model_class = OpenAIModel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We soemtime may want to use Azure openai models for some agents while openAI models for other agents. Using environment variable for the ModelFactory may not be a very good idea.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try to find a better way to do it in the next commit.

@Wendong-Fan
Copy link
Member

Thanks @L4zyy for the PR! Overall looks good. I have some questions

  • About the AzureOpenAIModel, do we need a seperate class for azure openai models? It seems the only differences between AzureOpenAIModel and OpenAIModel will be the creation of self._client. Should we just support azure models with OpenAIModel?
  • Should we just introduce enums in https://github.com/camel-ai/camel/blob/master/camel/types/enums.py to support the client creation? We can introduce somethings like: ModelType.Azure_GPT_3_5_TURBO and so on.

@dandansamax @Wendong-Fan any suggesitions?

Hi @lightaime @L4zyy,
I would suggest a separate class for azure openai for clear distinction and flexibility of future changes since azure may have different configurations or have unique features with openai (maybe solver feature update compared with openai);
Using enums is a great approach, I agree with moving azure_model_name_to_type to enums.py

@L4zyy
Copy link
Author

L4zyy commented Dec 10, 2023

Thanks @L4zyy for the PR! Overall looks good. I have some questions

  • About the AzureOpenAIModel, do we need a seperate class for azure openai models? It seems the only differences between AzureOpenAIModel and OpenAIModel will be the creation of self._client. Should we just support azure models with OpenAIModel?
  • Should we just introduce enums in https://github.com/camel-ai/camel/blob/master/camel/types/enums.py to support the client creation? We can introduce somethings like: ModelType.Azure_GPT_3_5_TURBO and so on.

@dandansamax @Wendong-Fan any suggesitions?

These are my initial ideas for integrating Azure OpenAI API. However, the API allows users to deploy models like GPT-3/GPT-4 with different deployment names. Therefore, when calling the self._client.chat.completions.create function, we should use the deployment name instead of the model name. This is why I want to use a new class for Azure OpenAI API.

In this MR, there is some unused code left over from when I was trying other ways to integrate the API. I apologize for that and will remove it in the next commit.

After considering your review, I think it would still be better to implement this integration in the OpenAIModel. I will try to integrate it in the OpenAIModel and commit a new implementation later.

I still have a question about the tests. Is it okay to leave some tests failed? If so, which tests should I pass before I can call for a review and merge to the master?

Thank you very much for the review.😊

@L4zyy
Copy link
Author

L4zyy commented Dec 10, 2023

Thanks @L4zyy for the PR! Overall looks good. I have some questions

  • About the AzureOpenAIModel, do we need a seperate class for azure openai models? It seems the only differences between AzureOpenAIModel and OpenAIModel will be the creation of self._client. Should we just support azure models with OpenAIModel?
  • Should we just introduce enums in https://github.com/camel-ai/camel/blob/master/camel/types/enums.py to support the client creation? We can introduce somethings like: ModelType.Azure_GPT_3_5_TURBO and so on.

@dandansamax @Wendong-Fan any suggesitions?

Hi @lightaime @L4zyy, I would suggest a separate class for azure openai for clear distinction and flexibility of future changes since azure may have different configurations or have unique features with openai (maybe solver feature update compared with openai); Using enums is a great approach, I agree with moving azure_model_name_to_type to enums.py

Thank you very much for your suggestions. I will consider whether it is better to integrate with a new class. Since the deployment name is user-specific, I think it may not be feasible to move it to ‘enums.py’ unless we ask the user to deploy the model with the same name as OpenAI? Instead, I will try to move this to the 'model_config_dict' instead of using an environment variable and see if it’s a good idea.

@dandansamax
Copy link
Collaborator

I still have a question about the tests. Is it okay to leave some tests failed? If so, which tests should I pass before I can call for a review and merge to the master?

No problem. The tests failed because doing MR from your fork repo cannot use Github secrets in the main repo. Just leave the CI tests failing if you has passed tests in the local env.

@dandansamax
Copy link
Collaborator

Thank you very much for your suggestions. I will consider whether it is better to integrate with a new class. Since the deployment name is user-specific, I think it may not be feasible to move it to ‘enums.py’ unless we ask the user to deploy the model with the same name as OpenAI? Instead, I will try to move this to the 'model_config_dict' instead of using an environment variable and see if it’s a good idea.

Hi @L4zyy, thank you for your contribution. Acutually, I don't think putting it in the model_config_dict is a good idea. model_config_dict stores some bottom-end parameters of model and should be comptiable for all GPT models. How about add a optional arguments in OpenAIModel and ModelFactory? so that it can be easily changed by the user.

@L4zyy
Copy link
Author

L4zyy commented Dec 11, 2023

Thank you very much for your suggestions. I will consider whether it is better to integrate with a new class. Since the deployment name is user-specific, I think it may not be feasible to move it to ‘enums.py’ unless we ask the user to deploy the model with the same name as OpenAI? Instead, I will try to move this to the 'model_config_dict' instead of using an environment variable and see if it’s a good idea.

Hi @L4zyy, thank you for your contribution. Acutually, I don't think putting it in the model_config_dict is a good idea. model_config_dict stores some bottom-end parameters of model and should be comptiable for all GPT models. How about add a optional arguments in OpenAIModel and ModelFactory? so that it can be easily changed by the user.

Thank you for the advice. I don’t think it’s worth adding a parameter in ‘ModelFactory’ and ‘ChatAgent’ only for Azure API. I have three plans to re-implement this integration:

  • Add several ‘AZURE_{OPENAI_MODEL_TYPE}’ model types and ‘is_azure’ function to enums.py. Then, change the Azure model type to the corresponding OpenAI model type at ‘ModelFactory’ and create an OpenAIModel.
  • Since the Azure API is just OpenAI API with a different deployment name, I think we can still add the ‘use_azure_openai_api=True’ and ‘deployment_name’ in ‘model_config_dict’. Then, pop these parameters out in ‘OpenAIModel._init_’ and pass the rest of the parameters to ‘self.model_config_dict’ variable.
  • We can add only one ‘AZURE’ model type in ‘enums.py’ and add a new AzureOpenAIModel class. We can decide how we parse the model_config_dict in its '_init_' function.

I prefer the third method since it is compatible with future differences between Azure API and OpenAI API. Meanwhile, it leaves the original OpenAIModel class unchanged. The first method will introduce extra variables in OpenAIModel and add an if statement in the run method, which makes it unclean. While the second method will have the same defect and introduce some redundant enums in ‘enums.py’ (Cause we need to add Azure API for every supported GPT model version.)

I have implemented the third method and updated the MR. I have run through nearly all tests I can run locally, and these are the tests that cannot pass locally:

  • test/functions/test_search_functions.py::test_google_api, which needs 'GOOGLE_API_KEY'
  • test/embeddings/test_openai_embedding.py::test_openai_embedding, which I don't know why it failed since I haven't changed any related code.
  • test/agents/test_chat_agent.py::test_chat_agent_stream_output, failed at AssertionError: assert 0 > 0, which I don't know why it failed.

Which one do you think is more appropriate for this integration? @lightaime @Wendong-Fan @dandansamax

@dandansamax
Copy link
Collaborator

Thank you for the advice. I don’t think it’s worth adding a parameter in ‘ModelFactory’ and ‘ChatAgent’ only for Azure API.

Thank you for your feedback. However, I think changing model name is a common operation. For exmaple, if I want to use OpenAI legacy APIs, it's very diffcult in the current implementation. But if we can pass model name to OpenAIModel, it's much easier for user to do it.

Also this feature can be widely used in the open source models.

I still don't think modifying model_config_dict is a good idea. This variable should keep constant to ensure that camel would pass exactly same model parameters to the backend API as the user set. If you really want to put all model configs in one dict, how about refactor the model_config_dict part by adding a "general backend config" containing model_config_dict with other backend parameters? What do you think?

I have implemented the third method and updated the MR. I have run through nearly all tests I can run locally, and these are the tests that cannot pass locally:

Ensure your newly created tests can be passed and it will be fine.

@L4zyy
Copy link
Author

L4zyy commented Dec 12, 2023

Thank you for your feedback. However, I think changing model name is a common operation. For exmaple, if I want to use OpenAI legacy APIs, it's very diffcult in the current implementation. But if we can pass model name to OpenAIModel, it's much easier for user to do it.

Also this feature can be widely used in the open source models.

I agree with you that adding another parameter to pass extra information would make the API integration much easier and flexible. However, I am not familiar with the implementation of the open-source model class, and I don’t want to introduce too much variation for this single API integration. If it’s okay to add a new parameter for this integration, I will re-implement it later.

I still don't think modifying model_config_dict is a good idea. This variable should keep constant to ensure that camel would pass exactly same model parameters to the backend API as the user set. If you really want to put all model configs in one dict, how about refactor the model_config_dict part by adding a "general backend config" containing model_config_dict with other backend parameters? What do you think?

I see. I will pass the extra information in the new parameter and see if it's better.

Ensure your newly created tests can be passed and it will be fine.

Okay, thanks for the clarification. 😊

@L4zyy
Copy link
Author

L4zyy commented Dec 13, 2023

Hi @dandansamax, I have re-implemented the integration as we discussed. The new implementation allows us to pass extra backend information through the backend_config_dict parameter. However, this version involved changes to a lot more files than the previous one. Specifically, I had to modify files related to the model factory, chat agent, and their tests. I have passed all tests that are not related to function tests (which may require their function keys) and open source models (since I have trouble downloading the weights of vicuna models). Please take a look and let me know your suggestions! 😊

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jan 14, 2024
@Wendong-Fan
Copy link
Member

Hi @L4zyy , thanks for the contribution! I'm going to review this PR but the pipeline still has error, would you like to fix this first? Thank!

@Wendong-Fan Wendong-Fan self-requested a review March 9, 2024 03:27
@L4zyy
Copy link
Author

L4zyy commented Mar 9, 2024

Hi @L4zyy , thanks for the contribution! I'm going to review this PR but the pipeline still has error, would you like to fix this first? Thank!

Certainly, I will update my code and address these errors later.

@L4zyy L4zyy mentioned this pull request Apr 4, 2024
12 tasks
@Wendong-Fan
Copy link
Member

close this pr since another new pr opened #499

@Wendong-Fan Wendong-Fan closed this Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Model Related to backend models size:L This PR changes 100-499 lines, ignoring generated files.
Projects
Status: Merged or Closed
Development

Successfully merging this pull request may close these issues.

[Feature Request] Support Azure OpenAI models
4 participants