hanlp-haystack 1.0.0__tar.gz → 2.0.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,20 @@
1
+ # Changelog
2
+
3
+ ## [integrations/hanlp-v1.0.1] - 2025-10-14
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - Missing decorator output for ChineseDocumentSplitter (#2377)
8
+
9
+
10
+ ### 🧹 Chores
11
+
12
+ - Standardize readmes - part 2 (#2205)
13
+
14
+ ## [integrations/hanlp-v1.0.0] - 2025-07-22
15
+
16
+ ### 🚀 Features
17
+
18
+ - Add new HanLP integration with ChineseDocumentSplitter (#1943)
19
+
20
+ <!-- generated by git-cliff -->
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanlp-haystack
3
- Version: 1.0.0
3
+ Version: 2.0.0
4
4
  Summary: An integration of Han Language Processing - HanLP as a ChineseDocumentSplitter component.
5
5
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/hanlp#readme
6
6
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
@@ -11,16 +11,15 @@ License-File: LICENSE.txt
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
19
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.9
20
+ Requires-Python: >=3.10
22
21
  Requires-Dist: hanlp>=2.1.1
23
- Requires-Dist: haystack-ai>=2.13.1
22
+ Requires-Dist: haystack-ai>=2.22.0
24
23
  Description-Content-Type: text/markdown
25
24
 
26
25
  # hanlp-haystack
@@ -28,19 +27,11 @@ Description-Content-Type: text/markdown
28
27
  [![PyPI - Version](https://img.shields.io/pypi/v/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
29
28
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
30
29
 
31
- -----
30
+ - [Integration page](https://haystack.deepset.ai/integrations/hanlp)
31
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/hanlp/CHANGELOG.md)
32
32
 
33
- ## Table of Contents
33
+ ---
34
34
 
35
- - [Installation](#installation)
36
- - [License](#license)
35
+ ## Contributing
37
36
 
38
- ## Installation
39
-
40
- ```console
41
- pip install hanlp-haystack
42
- ```
43
-
44
- ## License
45
-
46
- `hanlp-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
37
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -0,0 +1,13 @@
1
+ # hanlp-haystack
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
5
+
6
+ - [Integration page](https://haystack.deepset.ai/integrations/hanlp)
7
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/hanlp/CHANGELOG.md)
8
+
9
+ ---
10
+
11
+ ## Contributing
12
+
13
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -0,0 +1,28 @@
1
+ loaders:
2
+ - ignore_when_discovered:
3
+ - __init__
4
+ modules:
5
+ - haystack_integrations.components.preprocessors.hanlp.chinese_document_splitter
6
+ search_path:
7
+ - ../src
8
+ type: haystack_pydoc_tools.loaders.CustomPythonLoader
9
+ processors:
10
+ - do_not_filter_modules: false
11
+ documented_only: true
12
+ expression: null
13
+ skip_empty_modules: true
14
+ type: filter
15
+ - type: smart
16
+ - type: crossref
17
+ renderer:
18
+ description: HanLP integration for Haystack
19
+ id: integrations-hanlp
20
+ markdown:
21
+ add_member_class_prefix: false
22
+ add_method_class_prefix: true
23
+ classdef_code_block: false
24
+ descriptive_class_title: false
25
+ descriptive_module_title: true
26
+ filename: hanlp.md
27
+ title: HanLP
28
+ type: haystack_pydoc_tools.renderers.DocusaurusRenderer
@@ -7,7 +7,7 @@ name = "hanlp-haystack"
7
7
  dynamic = ["version"]
8
8
  description = 'An integration of Han Language Processing - HanLP as a ChineseDocumentSplitter component.'
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  license = "Apache-2.0"
12
12
  keywords = []
13
13
  authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
@@ -15,7 +15,6 @@ classifiers = [
15
15
  "License :: OSI Approved :: Apache Software License",
16
16
  "Development Status :: 4 - Beta",
17
17
  "Programming Language :: Python",
18
- "Programming Language :: Python :: 3.9",
19
18
  "Programming Language :: Python :: 3.10",
20
19
  "Programming Language :: Python :: 3.11",
21
20
  "Programming Language :: Python :: 3.12",
@@ -24,7 +23,7 @@ classifiers = [
24
23
  "Programming Language :: Python :: Implementation :: PyPy",
25
24
  ]
26
25
  dependencies = [
27
- "haystack-ai>=2.13.1",
26
+ "haystack-ai>=2.22.0",
28
27
  "hanlp>=2.1.1"
29
28
  ]
30
29
 
@@ -49,8 +48,8 @@ installer = "uv"
49
48
  dependencies = ["haystack-pydoc-tools", "ruff"]
50
49
 
51
50
  [tool.hatch.envs.default.scripts]
52
- docs = ["pydoc-markdown pydoc/config.yml"]
53
- fmt = "ruff check --fix {args} && ruff format {args}"
51
+ docs = ["pydoc-markdown pydoc/config_docusaurus.yml"]
52
+ fmt = "ruff check --fix {args}; ruff format {args}"
54
53
  fmt-check = "ruff check {args} && ruff format --check {args}"
55
54
 
56
55
  [tool.hatch.envs.test]
@@ -67,7 +66,7 @@ dependencies = [
67
66
  unit = 'pytest -m "not integration" {args:tests}'
68
67
  integration = 'pytest -m "integration" {args:tests}'
69
68
  all = 'pytest {args:tests}'
70
- cov-retry = 'all --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x'
69
+ cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x {args:tests}'
71
70
  types = """mypy -p haystack_integrations.components.preprocessors.hanlp {args}"""
72
71
 
73
72
  [tool.mypy]
@@ -83,12 +82,11 @@ module = [
83
82
  ignore_missing_imports = true
84
83
 
85
84
  [tool.black]
86
- target-version = ["py38"]
85
+ target-version = ["py39"]
87
86
  line-length = 120
88
87
  skip-string-normalization = true
89
88
 
90
89
  [tool.ruff]
91
- target-version = "py38"
92
90
  line-length = 120
93
91
 
94
92
  [tool.ruff.lint]
@@ -138,10 +136,6 @@ ignore = [
138
136
  "RUF001",
139
137
  "RUF002",
140
138
  ]
141
- unfixable = [
142
- # Don't touch unused imports
143
- "F401",
144
- ]
145
139
 
146
140
  [tool.ruff.lint.isort]
147
141
  known-first-party = ["haystack_integrations"]
@@ -2,8 +2,9 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ from collections.abc import Callable
5
6
  from copy import deepcopy
6
- from typing import Any, Callable, Dict, List, Literal, Optional, Tuple
7
+ from typing import Any, Literal
7
8
 
8
9
  from haystack import Document, component, logging
9
10
  from haystack.core.serialization import default_from_dict, default_to_dict
@@ -59,7 +60,7 @@ class ChineseDocumentSplitter:
59
60
  split_overlap: int = 200,
60
61
  split_threshold: int = 0,
61
62
  respect_sentence_boundary: bool = False,
62
- splitting_function: Optional[Callable] = None,
63
+ splitting_function: Callable | None = None,
63
64
  granularity: Literal["coarse", "fine"] = "coarse",
64
65
  ):
65
66
  """
@@ -148,7 +149,8 @@ class ChineseDocumentSplitter:
148
149
  msg = f"granularity must be one of 'coarse', 'fine', but got {granularity}"
149
150
  raise ValueError(msg)
150
151
 
151
- def run(self, documents: List[Document]) -> Dict[str, List[Document]]:
152
+ @component.output_types(documents=list[Document])
153
+ def run(self, documents: list[Document]) -> dict[str, list[Document]]:
152
154
  """
153
155
  Split documents into smaller chunks.
154
156
 
@@ -174,7 +176,7 @@ class ChineseDocumentSplitter:
174
176
  self.chinese_tokenizer = hanlp.load(hanlp.pretrained.tok.FINE_ELECTRA_SMALL_ZH)
175
177
  self.split_sent = hanlp.load(hanlp.pretrained.eos.UD_CTB_EOS_MUL)
176
178
 
177
- def _split_by_character(self, doc: Document) -> List[Document]:
179
+ def _split_by_character(self, doc: Document) -> list[Document]:
178
180
  """
179
181
  Define a function to handle Chinese clauses
180
182
 
@@ -201,7 +203,7 @@ class ChineseDocumentSplitter:
201
203
  )
202
204
 
203
205
  # Define a function to handle Chinese clauses
204
- def chinese_sentence_split(self, text: str) -> List[Dict[str, Any]]:
206
+ def chinese_sentence_split(self, text: str) -> list[dict[str, Any]]:
205
207
  """
206
208
  Split Chinese text into sentences.
207
209
 
@@ -222,7 +224,7 @@ class ChineseDocumentSplitter:
222
224
 
223
225
  return results
224
226
 
225
- def _split_document(self, doc: Document) -> List[Document]:
227
+ def _split_document(self, doc: Document) -> list[Document]:
226
228
  if self.split_by == "sentence" or self.respect_sentence_boundary:
227
229
  return self._split_by_hanlp_sentence(doc)
228
230
 
@@ -232,8 +234,8 @@ class ChineseDocumentSplitter:
232
234
  return self._split_by_character(doc)
233
235
 
234
236
  def _concatenate_sentences_based_on_word_amount(
235
- self, sentences: List[str], split_length: int, split_overlap: int, granularity: str
236
- ) -> Tuple[List[str], List[int], List[int]]:
237
+ self, sentences: list[str], split_length: int, split_overlap: int, granularity: str
238
+ ) -> tuple[list[str], list[int], list[int]]:
237
239
  """
238
240
  Groups the sentences into chunks of `split_length` words while respecting sentence boundaries.
239
241
 
@@ -250,11 +252,11 @@ class ChineseDocumentSplitter:
250
252
  chunk_word_count = 0
251
253
  chunk_starting_page_number = 1
252
254
  chunk_start_idx = 0
253
- current_chunk: List[str] = []
255
+ current_chunk: list[str] = []
254
256
 
255
257
  # output lists
256
258
  split_start_page_numbers = []
257
- list_of_splits: List[List[str]] = []
259
+ list_of_splits: list[list[str]] = []
258
260
  split_start_indices = []
259
261
 
260
262
  for sentence_idx, sentence in enumerate(sentences):
@@ -304,7 +306,7 @@ class ChineseDocumentSplitter:
304
306
 
305
307
  return text_splits, split_start_page_numbers, split_start_indices
306
308
 
307
- def _split_by_hanlp_sentence(self, doc: Document) -> List[Document]:
309
+ def _split_by_hanlp_sentence(self, doc: Document) -> list[Document]:
308
310
  """
309
311
  Split Chinese text into sentences.
310
312
 
@@ -341,8 +343,8 @@ class ChineseDocumentSplitter:
341
343
  return split_docs
342
344
 
343
345
  def _concatenate_units(
344
- self, elements: List[str], split_length: int, split_overlap: int, split_threshold: int
345
- ) -> Tuple[List[str], List[int], List[int]]:
346
+ self, elements: list[str], split_length: int, split_overlap: int, split_threshold: int
347
+ ) -> tuple[list[str], list[int], list[int]]:
346
348
  """
347
349
  Concatenates the elements into parts of split_length units.
348
350
 
@@ -363,9 +365,9 @@ class ChineseDocumentSplitter:
363
365
  # Otherwise, proceed as before
364
366
  step = split_length - split_overlap
365
367
  step = max(step, 1)
366
- text_splits: List[str] = []
367
- splits_pages: List[int] = []
368
- splits_start_idxs: List[int] = []
368
+ text_splits: list[str] = []
369
+ splits_pages: list[int] = []
370
+ splits_start_idxs: list[int] = []
369
371
  cur_start_idx = 0
370
372
  cur_page = 1
371
373
  segments = windowed(elements, n=split_length, step=step)
@@ -398,14 +400,14 @@ class ChineseDocumentSplitter:
398
400
  return text_splits, splits_pages, splits_start_idxs
399
401
 
400
402
  def _create_docs_from_splits(
401
- self, text_splits: List[str], splits_pages: List[int], splits_start_idxs: List[int], meta: Dict[str, Any]
402
- ) -> List[Document]:
403
+ self, text_splits: list[str], splits_pages: list[int], splits_start_idxs: list[int], meta: dict[str, Any]
404
+ ) -> list[Document]:
403
405
  """
404
406
  Creates Document objects from splits enriching them with page number and the metadata of the original document.
405
407
  """
406
- documents: List[Document] = []
408
+ documents: list[Document] = []
407
409
 
408
- for i, (txt, split_idx) in enumerate(zip(text_splits, splits_start_idxs)):
410
+ for i, (txt, split_idx) in enumerate(zip(text_splits, splits_start_idxs, strict=True)):
409
411
  copied_meta = deepcopy(meta)
410
412
  copied_meta["page_number"] = splits_pages[i]
411
413
  copied_meta["split_id"] = i
@@ -459,7 +461,7 @@ class ChineseDocumentSplitter:
459
461
  overlapping_range = (0, overlapping_range[1] - overlapping_range[0])
460
462
  previous_doc.meta["_split_overlap"].append({"doc_id": current_doc.id, "range": overlapping_range})
461
463
 
462
- def _number_of_sentences_to_keep(self, sentences: List[str], split_length: int, split_overlap: int) -> int:
464
+ def _number_of_sentences_to_keep(self, sentences: list[str], split_length: int, split_overlap: int) -> int:
463
465
  """
464
466
  Returns the number of sentences to keep in the next chunk based on the `split_overlap` and `split_length`.
465
467
 
@@ -485,7 +487,7 @@ class ChineseDocumentSplitter:
485
487
  break
486
488
  return num_sentences_to_keep
487
489
 
488
- def _split_by_function(self, doc: Document) -> List[Document]:
490
+ def _split_by_function(self, doc: Document) -> list[Document]:
489
491
  """
490
492
  Split a document using a custom splitting function.
491
493
 
@@ -514,7 +516,7 @@ class ChineseDocumentSplitter:
514
516
  meta=metadata,
515
517
  )
516
518
 
517
- def to_dict(self) -> Dict[str, Any]:
519
+ def to_dict(self) -> dict[str, Any]:
518
520
  """
519
521
  Serializes the component to a dictionary.
520
522
  """
@@ -532,7 +534,7 @@ class ChineseDocumentSplitter:
532
534
  return serialized
533
535
 
534
536
  @classmethod
535
- def from_dict(cls, data: Dict[str, Any]) -> "ChineseDocumentSplitter":
537
+ def from_dict(cls, data: dict[str, Any]) -> "ChineseDocumentSplitter":
536
538
  """
537
539
  Deserializes the component from a dictionary.
538
540
  """
@@ -123,7 +123,7 @@ class TestChineseDocumentSplitter:
123
123
  splitter.warm_up()
124
124
  result = splitter.run(documents=documents)
125
125
  assert len(result["documents"]) == 2
126
- for doc, split_doc in zip(documents, result["documents"]):
126
+ for doc, split_doc in zip(documents, result["documents"], strict=True):
127
127
  assert doc.meta.items() <= split_doc.meta.items()
128
128
 
129
129
  @pytest.mark.integration
@@ -136,7 +136,7 @@ class TestChineseDocumentSplitter:
136
136
  splitter.warm_up()
137
137
  result = splitter.run(documents=documents)
138
138
  assert len(result["documents"]) == 2
139
- for doc, split_doc in zip(documents, result["documents"]):
139
+ for doc, split_doc in zip(documents, result["documents"], strict=True):
140
140
  assert doc.id == split_doc.meta["source_id"]
141
141
 
142
142
  @pytest.mark.integration
@@ -1,21 +0,0 @@
1
- # hanlp-haystack
2
-
3
- [![PyPI - Version](https://img.shields.io/pypi/v/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
4
- [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hanlp-haystack.svg)](https://pypi.org/project/hanlp-haystack)
5
-
6
- -----
7
-
8
- ## Table of Contents
9
-
10
- - [Installation](#installation)
11
- - [License](#license)
12
-
13
- ## Installation
14
-
15
- ```console
16
- pip install hanlp-haystack
17
- ```
18
-
19
- ## License
20
-
21
- `hanlp-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
@@ -1,29 +0,0 @@
1
- loaders:
2
- - type: haystack_pydoc_tools.loaders.CustomPythonLoader
3
- search_path: [../src]
4
- modules: [
5
- "haystack_integrations.components.preprocessors.hanlp.chinese_document_splitter",
6
- ]
7
- ignore_when_discovered: ["__init__"]
8
- processors:
9
- - type: filter
10
- expression:
11
- documented_only: true
12
- do_not_filter_modules: false
13
- skip_empty_modules: true
14
- - type: smart
15
- - type: crossref
16
- renderer:
17
- type: haystack_pydoc_tools.renderers.ReadmeIntegrationRenderer
18
- excerpt: HanLP integration for Haystack
19
- category_slug: integrations-api
20
- title: HanLP
21
- slug: integrations-hanlp
22
- order: 100
23
- markdown:
24
- descriptive_class_title: false
25
- classdef_code_block: false
26
- descriptive_module_title: true
27
- add_method_class_prefix: true
28
- add_member_class_prefix: false
29
- filename: _readme_github.md