feat: Add DeepSeek Model component (#5443)

* feat: Add DeepSeek component

* Adiciona DeepseekModelComponent ao __init__.py

* [autofix.ci] apply automated fixes

* Add DeepSeek icon and update component files

* Add DeepSeek icon and update all related files

* [autofix.ci] apply automated fixes

* Change DeepSeek icon color to blue (#080c34)

* [autofix.ci] apply automated fixes

* Revert DeepSeek icon color to black

* [autofix.ci] apply automated fixes

* remove: name parameter from DeepSeekModel to avoid backwards compatibility issues

* test: add unit tests for DeepSeek model component with mocks

* fix: correct formatting issues in DeepSeek model tests

* feat: update DeepSeek icon color to #4c6cfc

* fix: make DeepSeek API key field required

* fix: format SecretStrInput to comply with line length limit in DeepSeekModelComponent

* feat: add dark mode support for component icon

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
Raphael Valdetaro 2025-01-17 14:45:39 -03:00 • committed by GitHub
commit 656f9f30db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 339 additions and 0 deletions

View file

@ -0,0 +1,112 @@
from unittest.mock import MagicMock
import pytest
from langflow.components.models import DeepSeekModelComponent
from langflow.custom import Component
from langflow.custom.utils import build_custom_component_template
def test_deepseek_initialization():
component = DeepSeekModelComponent()
assert component.display_name == "DeepSeek"
assert component.description == "Generate text using DeepSeek LLMs."
assert component.icon == "DeepSeek"
def test_deepseek_template():
deepseek = DeepSeekModelComponent()
component = Component(_code=deepseek._code)
frontend_node, _ = build_custom_component_template(component)
# Verify basic structure
assert isinstance(frontend_node, dict)
# Verify inputs
assert "template" in frontend_node
input_names = [input_["name"] for input_ in frontend_node["template"].values() if isinstance(input_, dict)]
expected_inputs = [
"max_tokens",
"model_kwargs",
"json_mode",
"model_name",
"api_base",
"api_key",
"temperature",
"seed",
]
for input_name in expected_inputs:
assert input_name in input_names
@pytest.mark.parametrize(
("temperature", "max_tokens"),
[
(0.5, 100),
(1.0, 500),
(1.5, 1000),
],
)
@pytest.fixture
def mock_chat_openai(mocker):
return mocker.patch("langchain_openai.ChatOpenAI")
def test_deepseek_build_model(mock_chat_openai):
component = DeepSeekModelComponent()
component.temperature = 0.7
component.max_tokens = 100
component.api_key = "test-key"
# Mock the ChatOpenAI instance
mock_instance = MagicMock()
mock_chat_openai.return_value = mock_instance
model = component.build_model()
# Verify ChatOpenAI was called with correct params
mock_chat_openai.assert_called_once_with(
max_tokens=100,
model_kwargs={},
model="deepseek-chat",
base_url="https://api.deepseek.com",
api_key="test-key",
temperature=0.7,
seed=1,
streaming=False,
)
assert model == mock_instance
def test_deepseek_get_models(mocker):
component = DeepSeekModelComponent()
# Mock requests.get
mock_get = mocker.patch("requests.get")
mock_response = MagicMock()
mock_response.json.return_value = {"data": [{"id": "deepseek-chat"}, {"id": "deepseek-coder"}]}
mock_get.return_value = mock_response
# Test with API key
component.api_key = "test-key"
models = component.get_models()
assert models == ["deepseek-chat", "deepseek-coder"]
# Verify API call
mock_get.assert_called_once_with(
"https://api.deepseek.com/models",
headers={"Authorization": "Bearer test-key", "Accept": "application/json"},
timeout=10,
)
def test_deepseek_error_handling(mock_chat_openai):
component = DeepSeekModelComponent()
component.api_key = "invalid-key"
# Mock ChatOpenAI to raise exception
mock_chat_openai.side_effect = Exception("Invalid API key")
with pytest.raises(Exception, match="Invalid API key"):
component.build_model()