deepl-haystack 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright 2024 Dribia Data Research S.L. (https://www.dribia.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.1
2
+ Name: deepl-haystack
3
+ Version: 0.1.0
4
+ Summary: Haystack integration with DeepL translation services provider.
5
+ Home-page: https://github.com/dribia/deepl-haystack
6
+ License: Apache-2.0
7
+ Keywords: haystack,deepl,translation,nlp
8
+ Author: Albert Iribarne
9
+ Author-email: iribarne@dribia.com
10
+ Maintainer: Albert Iribarne
11
+ Maintainer-email: iribarne@dribia.com
12
+ Requires-Python: >=3.9,<3.13
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Dist: deepl (>=1.18.0,<2.0.0)
24
+ Requires-Dist: haystack-ai (>=2.3.0,<3.0.0)
25
+ Project-URL: Bug Tracker, https://github.com/dribia/deepl-haystack/issues
26
+ Project-URL: Repository, https://github.com/dribia/deepl-haystack
27
+ Description-Content-Type: text/markdown
28
+
29
+ DeepL Haystack Integration
30
+ ==========================
31
+
32
+ | | |
33
+ |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
34
+ | CI/CD | [![Tests](https://github.com/dribia/deepl-haystack/actions/workflows/test.yml/badge.svg)](https://github.com/dribia/deepl-haystack/actions/workflows/test.yml) [![Coverage Status](https://img.shields.io/codecov/c/github/dribia/driconfig)](https://codecov.io/gh/dribia/driconfig) [![Tests](https://github.com/dribia/deepl-haystack/actions/workflows/lint.yml/badge.svg)](https://github.com/dribia/deepl-haystack/actions/workflows/lint.yml) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) |
35
+ | Package | [![PyPI](https://img.shields.io/pypi/v/deepl-haystack)](https://pypi.org/project/deepl-haystack/) ![PyPI - Downloads](https://img.shields.io/pypi/dm/deepl-haystack?color=blue&logo=pypi&logoColor=gold) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/deepl-haystack?logo=python&logoColor=gold) [![GitHub](https://img.shields.io/github/license/dribia/deepl-haystack?color=blue)](LICENSE) |
36
+ ---
37
+
38
+ **Table of Contents**
39
+
40
+ - [deepl-haystack](#deepl-haystack-integration)
41
+ - [Installation](#installation)
42
+ - [Contributing](#contributing)
43
+ - [License](#license)
44
+
45
+ ## Installation
46
+
47
+ ```console
48
+ pip install deepl-haystack
49
+ ```
50
+
51
+ ## Contributing
52
+
53
+ [Poetry](https://python-poetry.org) is the best way to interact with this project, to install it,
54
+ follow the official [Poetry installation guide](https://python-poetry.org/docs/#installation).
55
+
56
+ With `poetry` installed, one can install the project dependencies with:
57
+
58
+ ```shell
59
+ poetry install
60
+ ```
61
+
62
+ Then, to run the tests:
63
+
64
+ ```shell
65
+ make test
66
+ ```
67
+
68
+ To run the linters `ruff` and `mypy`:
69
+
70
+ ```shell
71
+ make lint
72
+ ```
73
+
74
+ To apply all code formatting:
75
+
76
+ ```shell
77
+ make format
78
+ ```
79
+
80
+ ## License
81
+
82
+ `google-vertex-haystack` is distributed under the terms of the
83
+ [MIT](https://opensource.org/license/mit) license.
84
+
@@ -0,0 +1,55 @@
1
+ DeepL Haystack Integration
2
+ ==========================
3
+
4
+ | | |
5
+ |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
6
+ | CI/CD | [![Tests](https://github.com/dribia/deepl-haystack/actions/workflows/test.yml/badge.svg)](https://github.com/dribia/deepl-haystack/actions/workflows/test.yml) [![Coverage Status](https://img.shields.io/codecov/c/github/dribia/driconfig)](https://codecov.io/gh/dribia/driconfig) [![Tests](https://github.com/dribia/deepl-haystack/actions/workflows/lint.yml/badge.svg)](https://github.com/dribia/deepl-haystack/actions/workflows/lint.yml) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) |
7
+ | Package | [![PyPI](https://img.shields.io/pypi/v/deepl-haystack)](https://pypi.org/project/deepl-haystack/) ![PyPI - Downloads](https://img.shields.io/pypi/dm/deepl-haystack?color=blue&logo=pypi&logoColor=gold) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/deepl-haystack?logo=python&logoColor=gold) [![GitHub](https://img.shields.io/github/license/dribia/deepl-haystack?color=blue)](LICENSE) |
8
+ ---
9
+
10
+ **Table of Contents**
11
+
12
+ - [deepl-haystack](#deepl-haystack-integration)
13
+ - [Installation](#installation)
14
+ - [Contributing](#contributing)
15
+ - [License](#license)
16
+
17
+ ## Installation
18
+
19
+ ```console
20
+ pip install deepl-haystack
21
+ ```
22
+
23
+ ## Contributing
24
+
25
+ [Poetry](https://python-poetry.org) is the best way to interact with this project, to install it,
26
+ follow the official [Poetry installation guide](https://python-poetry.org/docs/#installation).
27
+
28
+ With `poetry` installed, one can install the project dependencies with:
29
+
30
+ ```shell
31
+ poetry install
32
+ ```
33
+
34
+ Then, to run the tests:
35
+
36
+ ```shell
37
+ make test
38
+ ```
39
+
40
+ To run the linters `ruff` and `mypy`:
41
+
42
+ ```shell
43
+ make lint
44
+ ```
45
+
46
+ To apply all code formatting:
47
+
48
+ ```shell
49
+ make format
50
+ ```
51
+
52
+ ## License
53
+
54
+ `google-vertex-haystack` is distributed under the terms of the
55
+ [MIT](https://opensource.org/license/mit) license.
@@ -0,0 +1,10 @@
1
+ """DeepL Haystack integration."""
2
+
3
+ from .components.translators.deepl.translator import (
4
+ DeepLDocumentTranslator,
5
+ DeepLTextTranslator,
6
+ )
7
+
8
+ __version__ = "0.1.0"
9
+
10
+ __all__ = ["DeepLDocumentTranslator", "DeepLTextTranslator"]
@@ -0,0 +1,203 @@
1
+ """DeepL translator component."""
2
+
3
+ from typing import Any, Dict, List, Optional, Union
4
+
5
+ from deepl import Formality, TextResult, Translator
6
+ from haystack import Document, component, default_from_dict, default_to_dict
7
+ from haystack.utils import Secret, deserialize_secrets_inplace
8
+
9
+
10
+ @component
11
+ class DeepLTextTranslator:
12
+ """Enables translation of text using DeepL API."""
13
+
14
+ def __init__(
15
+ self,
16
+ api_key: Secret = Secret.from_env_var("DEEPL_API_KEY"), # noqa: B008
17
+ source_lang: Optional[str] = None,
18
+ target_lang: str = "EN-US",
19
+ formality: Union[str, Formality, None] = None,
20
+ ):
21
+ """Create a DeepLTextTranslator component.
22
+
23
+ Args:
24
+ api_key: DeepL API Authentication Key.
25
+ source_lang: Language code of the input text, e.g. "DE"
26
+ for German, or "ES" for Spanish.
27
+ target_lang: Language code to translate the text into,
28
+ defaults to "EN", for English.
29
+ formality: Desired formality for translation, as
30
+ Formality enum, "less", "more", "prefer_less",
31
+ "prefer_more", or "default".
32
+
33
+ """
34
+ self.api_key: Secret = api_key
35
+ self.client: Translator = Translator(auth_key=self.api_key.resolve_value())
36
+ self.source_lang: Optional[str] = source_lang
37
+ self.target_lang: str = target_lang
38
+ self.formality: Formality = Formality(formality or Formality.DEFAULT)
39
+
40
+ @component.output_types(translation=str, meta=Dict[str, Any])
41
+ def run(self, text: str, source_lang: Optional[str] = None):
42
+ """Translate a single string.
43
+
44
+ Args:
45
+ text: Text to translate.
46
+ source_lang: Language code of the input text, e.g. "DE"
47
+ for German, or "ES" for Spanish. If informed, takes
48
+ precedence over the `source_lang` informed at
49
+ initialization.
50
+
51
+ Returns: A dictionary with the following keys:
52
+ - `translation`: The translation of the input text.
53
+ - `meta`: Information about the usage of the model.
54
+
55
+ """
56
+ if not isinstance(text, str):
57
+ raise TypeError(
58
+ "DeepLTextTranslator expects a string as an input. "
59
+ "In case you want to translate a list of Documents, "
60
+ "please use the DeepLDocumentTranslator."
61
+ )
62
+
63
+ translation = self.client.translate_text(
64
+ text,
65
+ source_lang=source_lang or self.source_lang or None,
66
+ target_lang=self.target_lang,
67
+ formality=self.formality,
68
+ )
69
+ assert isinstance(translation, TextResult)
70
+ meta = {
71
+ "source_lang": translation.detected_source_lang,
72
+ "target_lang": self.target_lang,
73
+ }
74
+ return {"translation": translation.text, "meta": meta}
75
+
76
+ def to_dict(self) -> Dict[str, Any]:
77
+ """Serializes the component to a dictionary.
78
+
79
+ Returns: Dictionary with serialized data.
80
+
81
+ """
82
+ return default_to_dict(
83
+ self,
84
+ api_key=self.api_key.to_dict(),
85
+ source_lang=self.source_lang,
86
+ target_lang=self.target_lang,
87
+ formality=self.formality.value,
88
+ )
89
+
90
+ @classmethod
91
+ def from_dict(cls, data: Dict[str, Any]) -> "DeepLTextTranslator":
92
+ """Deserializes the component from a dictionary.
93
+
94
+ Args:
95
+ data: Dictionary to deserialize from.
96
+
97
+ Returns: Deserialized component.
98
+
99
+ """
100
+ deserialize_secrets_inplace(data["init_parameters"], keys=["api_key"])
101
+ return default_from_dict(cls, data)
102
+
103
+
104
+ @component
105
+ class DeepLDocumentTranslator:
106
+ """Enables translation of Haystack Documents using DeepL API."""
107
+
108
+ def __init__(
109
+ self,
110
+ api_key: Secret = Secret.from_env_var("DEEPL_API_KEY"), # noqa: B008
111
+ source_lang: Optional[str] = None,
112
+ target_lang: str = "EN-US",
113
+ formality: Union[str, Formality, None] = None,
114
+ ):
115
+ """Create a DeepLDocumentTranslator component.
116
+
117
+ Args:
118
+ api_key: DeepL API Authentication Key.
119
+ source_lang: Language code of the input text, e.g. "DE"
120
+ for German, or "ES" for Spanish.
121
+ target_lang: Language code to translate the text into,
122
+ defaults to "EN", for English.
123
+ formality: Desired formality for translation, as
124
+ Formality enum, "less", "more", "prefer_less",
125
+ "prefer_more", or "default".
126
+
127
+ """
128
+ self.api_key: Secret = api_key
129
+ self.client: Translator = Translator(auth_key=self.api_key.resolve_value())
130
+ self.source_lang: Optional[str] = source_lang
131
+ self.target_lang: str = target_lang
132
+ self.formality: Formality = Formality(formality or Formality.DEFAULT)
133
+
134
+ @component.output_types(documents=List[Document])
135
+ def run(self, documents: List[Document], source_lang: Optional[str] = None):
136
+ """Translate a list of Haystack Documents.
137
+
138
+ Args:
139
+ documents: Documents to translate.
140
+ source_lang: Language code of the input documents text,
141
+ e.g. "DE" for German, or "ES" for Spanish. If informed,
142
+ takes precedence over the `source_lang` informed at
143
+ initialization.
144
+
145
+ Returns: A list of documents with the translated text.
146
+ Original document metadata is preserved.
147
+
148
+ """
149
+ if not (
150
+ isinstance(documents, list)
151
+ and all(isinstance(doc, Document) for doc in documents)
152
+ ):
153
+ raise TypeError(
154
+ "DeepLTextTranslator expects a list of Haystack documents as input."
155
+ )
156
+
157
+ translations = self.client.translate_text(
158
+ [doc.content for doc in documents],
159
+ source_lang=source_lang or self.source_lang or None,
160
+ target_lang=self.target_lang,
161
+ formality=self.formality,
162
+ )
163
+ assert isinstance(translations, list)
164
+ for _translation in translations:
165
+ pass
166
+ return [
167
+ Document(
168
+ content=translation.text,
169
+ meta=dict(
170
+ **document.meta,
171
+ source_lang=translation.detected_source_lang,
172
+ target_lang=self.target_lang,
173
+ ),
174
+ )
175
+ for document, translation in zip(documents, translations)
176
+ ]
177
+
178
+ def to_dict(self) -> Dict[str, Any]:
179
+ """Serializes the component to a dictionary.
180
+
181
+ Returns: Dictionary with serialized data.
182
+
183
+ """
184
+ return default_to_dict(
185
+ self,
186
+ api_key=self.api_key.to_dict(),
187
+ source_lang=self.source_lang,
188
+ target_lang=self.target_lang,
189
+ formality=self.formality.value,
190
+ )
191
+
192
+ @classmethod
193
+ def from_dict(cls, data: Dict[str, Any]) -> "DeepLTextTranslator":
194
+ """Deserializes the component from a dictionary.
195
+
196
+ Args:
197
+ data: Dictionary to deserialize from.
198
+
199
+ Returns: Deserialized component.
200
+
201
+ """
202
+ deserialize_secrets_inplace(data["init_parameters"], keys=["api_key"])
203
+ return default_from_dict(cls, data)
@@ -0,0 +1,107 @@
1
+ [tool.poetry]
2
+ name = "deepl-haystack"
3
+ version = "0.1.0"
4
+ description = "Haystack integration with DeepL translation services provider."
5
+ authors = ["Albert Iribarne <iribarne@dribia.com>"]
6
+ maintainers = ["Albert Iribarne <iribarne@dribia.com>", "Dribia Data Research <code@dribia.com>"]
7
+ license = "Apache-2.0"
8
+ readme = "README.md"
9
+ repository = "https://github.com/dribia/deepl-haystack"
10
+ homepage = "https://github.com/dribia/deepl-haystack"
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Science/Research",
14
+ "Operating System :: OS Independent",
15
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
16
+ ]
17
+ keywords = ["haystack", "deepl", "translation", "nlp"]
18
+
19
+ [tool.poetry.urls]
20
+ "Bug Tracker" = "https://github.com/dribia/deepl-haystack/issues"
21
+
22
+ [tool.poetry.dependencies]
23
+ python = ">=3.9,<3.13"
24
+ deepl = "^1.18.0"
25
+ haystack-ai = "^2.3.0"
26
+
27
+ [tool.poetry.group.test.dependencies]
28
+ pytest = "^8.3.1"
29
+ pytest-mock = "^3.14.0"
30
+ pytest-cov = "^5.0.0"
31
+
32
+ [tool.poetry.group.lint.dependencies]
33
+ ruff = "0.5.5"
34
+ mypy = "1.11.0"
35
+
36
+ [tool.poetry.group.dev.dependencies]
37
+ pre-commit = "^3.7.1"
38
+
39
+ [tool.ruff]
40
+
41
+ [tool.ruff.lint]
42
+ select = [
43
+ "E", # pycodestyle errors
44
+ "W", # pycodestyle warnings
45
+ "F", # pyflakes
46
+ "I", # isort
47
+ "C", # flake8-comprehensions
48
+ "B", # flake8-bugbear
49
+ "D", # pydocstyle
50
+ "UP", # pyupgrade
51
+ ]
52
+ ignore = [
53
+ "E501", # line too long, handled by black
54
+ "C901", # function is too complex
55
+ "D206", # indent with spaces, not recommended with formatter
56
+ "W191", # tab-indentation, not recommended with formatter
57
+ "D203", # no-blank-line-before-class
58
+ "D213", # multi-line-summary-second-line
59
+ ]
60
+
61
+ [tool.ruff.lint.per-file-ignores]
62
+ "tests/*" = ["D"]
63
+
64
+ [tool.ruff.lint.isort]
65
+
66
+ [tool.ruff.lint.pydocstyle]
67
+ convention = "google"
68
+
69
+ [tool.mypy]
70
+ plugins = []
71
+ strict_optional = true
72
+ ignore_missing_imports = false
73
+
74
+ [[tool.mypy.overrides]]
75
+ module = [
76
+ "haystack",
77
+ "haystack.utils"
78
+ ]
79
+ ignore_missing_imports = true
80
+
81
+ [tool.pytest.ini_options]
82
+ minversion = "8.0"
83
+ addopts = "--verbose"
84
+ filterwarnings = 'error'
85
+ xfail_strict = true
86
+ testpaths = ["tests"]
87
+ markers = []
88
+
89
+ [tool.coverage.run]
90
+ source = ["deepl_haystack", "tests"]
91
+ branch = true
92
+
93
+ [tool.coverage.report]
94
+ precision = 2
95
+ exclude_lines = [
96
+ 'pragma: no cover',
97
+ 'raise NotImplementedError',
98
+ 'if TYPE_CHECKING:',
99
+ '@overload',
100
+ ]
101
+
102
+ [tool.coverage.xml]
103
+ output = "coverage.xml"
104
+
105
+ [build-system]
106
+ requires = ["poetry-core"]
107
+ build-backend = "poetry.core.masonry.api"