From 6f114e19221f444f74e54c6ab177f30bd2a752f1 Mon Sep 17 00:00:00 2001 From: Riddhimaan-Senapati Date: Thu, 9 Jan 2025 00:03:35 +0530 Subject: [PATCH 1/4] added basic code for deepseek provider in aisuite using the openai provider code as inspiration. --- aisuite/providers/deepseek_provider.py | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 aisuite/providers/deepseek_provider.py diff --git a/aisuite/providers/deepseek_provider.py b/aisuite/providers/deepseek_provider.py new file mode 100644 index 0000000..7bc7f2a --- /dev/null +++ b/aisuite/providers/deepseek_provider.py @@ -0,0 +1,34 @@ +import openai +import os +from aisuite.provider import Provider + + +class OpenaiProvider(Provider): + def __init__(self, **config): + """ + Initialize the DeepSeek provider with the given configuration. + Pass the entire configuration dictionary to the OpenAI client constructor. + """ + # Ensure API key is provided either in config or via environment variable + config.setdefault("api_key", os.getenv("DEEPSEEK_API_KEY")) + if not config["api_key"]: + raise ValueError( + "DeepSeek API key is missing. Please provide it in the config or set the OPENAI_API_KEY environment variable." + ) + config["base_url"]="https://api.deepseek.com" + + # NOTE: We could choose to remove above lines for api_key since OpenAI will automatically + # infer certain values from the environment variables. + # Eg: OPENAI_API_KEY, OPENAI_ORG_ID, OPENAI_PROJECT_ID. Except for OPEN_AI_BASE_URL which has to be the deepseek url + + # Pass the entire config to the OpenAI client constructor + self.client = openai.OpenAI(**config) + + def chat_completions_create(self, model, messages, **kwargs): + # Any exception raised by OpenAI will be returned to the caller. + # Maybe we should catch them and raise a custom LLMError. + return self.client.chat.completions.create( + model=model, + messages=messages, + **kwargs # Pass any additional arguments to the OpenAI API + ) From f4f51d85897ffad55a3b5971a84bb4c22f5742ea Mon Sep 17 00:00:00 2001 From: Riddhimaan-Senapati Date: Thu, 9 Jan 2025 00:07:06 +0530 Subject: [PATCH 2/4] added tests for deepseek provider as well. --- aisuite/providers/deepseek_provider.py | 2 +- tests/providers/test_deepseek_provider.py | 46 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/providers/test_deepseek_provider.py diff --git a/aisuite/providers/deepseek_provider.py b/aisuite/providers/deepseek_provider.py index 7bc7f2a..8ba7c5b 100644 --- a/aisuite/providers/deepseek_provider.py +++ b/aisuite/providers/deepseek_provider.py @@ -3,7 +3,7 @@ from aisuite.provider import Provider -class OpenaiProvider(Provider): +class DeepseekProvider(Provider): def __init__(self, **config): """ Initialize the DeepSeek provider with the given configuration. diff --git a/tests/providers/test_deepseek_provider.py b/tests/providers/test_deepseek_provider.py new file mode 100644 index 0000000..1ab6f1c --- /dev/null +++ b/tests/providers/test_deepseek_provider.py @@ -0,0 +1,46 @@ +from unittest.mock import MagicMock, patch + +import pytest + +from aisuite.providers.deepseek_provider import DeepseekProvider + + +@pytest.fixture(autouse=True) +def set_api_key_env_var(monkeypatch): + """Fixture to set environment variables for tests.""" + monkeypatch.setenv("DEEPSEEK_API_KEY", "test-api-key") + + +def test_groq_provider(): + """High-level test that the provider is initialized and chat completions are requested successfully.""" + + user_greeting = "Hello!" + message_history = [{"role": "user", "content": user_greeting}] + selected_model = "our-favorite-model" + chosen_temperature = 0.75 + response_text_content = "mocked-text-response-from-model" + + provider = DeepseekProvider() + mock_response = MagicMock() + mock_response.choices = [MagicMock()] + mock_response.choices[0].message = MagicMock() + mock_response.choices[0].message.content = response_text_content + + with patch.object( + provider.client.chat.completions, + "create", + return_value=mock_response, + ) as mock_create: + response = provider.chat_completions_create( + messages=message_history, + model=selected_model, + temperature=chosen_temperature, + ) + + mock_create.assert_called_with( + messages=message_history, + model=selected_model, + temperature=chosen_temperature, + ) + + assert response.choices[0].message.content == response_text_content From 4e429e07f187d9b8bf8783bb13cff9051202e7ea Mon Sep 17 00:00:00 2001 From: Riddhimaan-Senapati Date: Fri, 10 Jan 2025 08:35:32 +0530 Subject: [PATCH 3/4] added a guide on how to use DeepSeek LLMs with aisuite --- aisuite/providers/deepseek_provider.py | 2 +- guides/README.md | 1 + guides/deepseek.md | 46 ++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 guides/deepseek.md diff --git a/aisuite/providers/deepseek_provider.py b/aisuite/providers/deepseek_provider.py index 8ba7c5b..40c6e45 100644 --- a/aisuite/providers/deepseek_provider.py +++ b/aisuite/providers/deepseek_provider.py @@ -1,6 +1,6 @@ import openai import os -from aisuite.provider import Provider +from aisuite.provider import Provider, LLMError class DeepseekProvider(Provider): diff --git a/guides/README.md b/guides/README.md index 7c2c062..5077458 100644 --- a/guides/README.md +++ b/guides/README.md @@ -12,6 +12,7 @@ Here are the instructions for: - [OpenAI](openai.md) - [SambaNova](sambanova.md) - [xAI](xai.md) +- [DeepSeek](deepseek.md) Unless otherwise stated, these guides have not been endorsed by the providers. diff --git a/guides/deepseek.md b/guides/deepseek.md new file mode 100644 index 0000000..9985a11 --- /dev/null +++ b/guides/deepseek.md @@ -0,0 +1,46 @@ +# DeepSeek + +To use DeepSeek with `aisuite`, you’ll need an [DeepSeek account](https://platform.deepseek.com). After logging in, go to the [API Keys](https://platform.deepseek.com/api_keys) section in your account settings and generate a new key. Once you have your key, add it to your environment as follows: + +```shell +export DEEPSEEK_API_KEY="your-deepseek-api-key" +``` + +## Create a Chat Completion + +(Note: The DeepSeek uses an API format consistent with OpenAI, hence why we need to install OpenAI, there is no DeepSeek Library at least not for now) + +Install the `openai` Python client: + +Example with pip: +```shell +pip install openai +``` + +Example with poetry: +```shell +poetry add openai +``` + +In your code: +```python +import aisuite as ai +client = ai.Client() + +provider = "deepseek" +model_id = "deepseek-chat" + +messages = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "What’s the weather like in San Francisco?"}, +] + +response = client.chat.completions.create( + model=f"{provider}:{model_id}", + messages=messages, +) + +print(response.choices[0].message.content) +``` + +Happy coding! If you’d like to contribute, please read our [Contributing Guide](../CONTRIBUTING.md). From abe10594f56aba3d4092cd409082020aa0692fe7 Mon Sep 17 00:00:00 2001 From: Riddhimaan-Senapati Date: Sun, 19 Jan 2025 15:32:55 -0500 Subject: [PATCH 4/4] reformated the code using black as requested. --- aisuite/providers/deepseek_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aisuite/providers/deepseek_provider.py b/aisuite/providers/deepseek_provider.py index 40c6e45..16327c5 100644 --- a/aisuite/providers/deepseek_provider.py +++ b/aisuite/providers/deepseek_provider.py @@ -15,7 +15,7 @@ def __init__(self, **config): raise ValueError( "DeepSeek API key is missing. Please provide it in the config or set the OPENAI_API_KEY environment variable." ) - config["base_url"]="https://api.deepseek.com" + config["base_url"] = "https://api.deepseek.com" # NOTE: We could choose to remove above lines for api_key since OpenAI will automatically # infer certain values from the environment variables.