kgmodule-utils 0.4.3__tar.gz → 0.4.5__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.
Files changed (27) hide show
  1. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/PKG-INFO +2 -2
  2. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/README.md +1 -1
  3. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/pyproject.toml +1 -1
  4. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/__init__.py +1 -1
  5. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/embedder.py +29 -11
  6. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/synthesis/_image.py +5 -1
  7. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/synthesis/_text.py +25 -0
  8. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/LICENSE +0 -0
  9. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/embed.py +0 -0
  10. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/extractor.py +0 -0
  11. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/module.py +0 -0
  12. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/pipeline.py +0 -0
  13. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/py.typed +0 -0
  14. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/retrieval/__init__.py +0 -0
  15. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/retrieval/hits.py +0 -0
  16. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/semantic.py +0 -0
  17. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/snapshots/__init__.py +0 -0
  18. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/snapshots/manager.py +0 -0
  19. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/snapshots/models.py +0 -0
  20. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/specs.py +0 -0
  21. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/store.py +0 -0
  22. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/synthesis/__init__.py +0 -0
  23. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/synthesis/_config.py +0 -0
  24. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/synthesis/factory.py +0 -0
  25. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/worker/__init__.py +0 -0
  26. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/worker/client.py +0 -0
  27. {kgmodule_utils-0.4.3 → kgmodule_utils-0.4.5}/src/kg_utils/worker/ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kgmodule-utils
3
- Version: 0.4.3
3
+ Version: 0.4.5
4
4
  Summary: Shared types, graph store, semantic index, and pipeline base for the KGModule SDK
5
5
  License: Elastic-2.0
6
6
  License-File: LICENSE
@@ -35,7 +35,7 @@ Description-Content-Type: text/markdown
35
35
 
36
36
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
37
37
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
38
- [![Version](https://img.shields.io/badge/version-0.4.0-blue.svg)](https://github.com/Flux-Frontiers/KG_utils/releases)
38
+ [![Version](https://img.shields.io/badge/version-0.4.4-blue.svg)](https://github.com/Flux-Frontiers/KG_utils/releases)
39
39
  [![CI](https://github.com/Flux-Frontiers/KG_utils/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/KG_utils/actions/workflows/ci.yml)
40
40
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
41
41
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
3
3
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
4
- [![Version](https://img.shields.io/badge/version-0.4.0-blue.svg)](https://github.com/Flux-Frontiers/KG_utils/releases)
4
+ [![Version](https://img.shields.io/badge/version-0.4.4-blue.svg)](https://github.com/Flux-Frontiers/KG_utils/releases)
5
5
  [![CI](https://github.com/Flux-Frontiers/KG_utils/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/KG_utils/actions/workflows/ci.yml)
6
6
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
7
7
 
@@ -10,7 +10,7 @@ build-backend = "poetry.core.masonry.api"
10
10
 
11
11
  [project]
12
12
  name = "kgmodule-utils"
13
- version = "0.4.3"
13
+ version = "0.4.5"
14
14
  description = "Shared types, graph store, semantic index, and pipeline base for the KGModule SDK"
15
15
  readme = "README.md"
16
16
  license = { text = "Elastic-2.0" }
@@ -24,4 +24,4 @@ Optional extras
24
24
  pip install 'kgmodule-utils[synthesis-mflux]' # + mflux (Apple Silicon local gen)
25
25
  """
26
26
 
27
- __version__ = "0.4.3"
27
+ __version__ = "0.4.5"
@@ -34,12 +34,12 @@ License: Elastic 2.0
34
34
 
35
35
  from __future__ import annotations
36
36
 
37
+ import importlib
37
38
  import os
38
39
  from typing import Any
39
40
 
40
41
  from kg_utils.embed import DEFAULT_MODEL, KNOWN_MODELS, resolve_model_path
41
42
 
42
-
43
43
  # ---------------------------------------------------------------------------
44
44
  # Abstract base
45
45
  # ---------------------------------------------------------------------------
@@ -75,7 +75,7 @@ class Embedder:
75
75
  # ---------------------------------------------------------------------------
76
76
 
77
77
 
78
- def load_sentence_transformer(model_name: str = DEFAULT_MODEL) -> Any:
78
+ def load_sentence_transformer(model_name: str = DEFAULT_MODEL, device: str | None = None) -> Any:
79
79
  """Load a ``SentenceTransformer`` with the canonical safe-load sequence.
80
80
 
81
81
  Resolution order:
@@ -90,13 +90,22 @@ def load_sentence_transformer(model_name: str = DEFAULT_MODEL) -> Any:
90
90
  retry loops leave stale thread state that causes SIGBUS on the first
91
91
  ``encode()`` call.
92
92
 
93
+ Device precedence: explicit *device* arg > ``KG_EMBED_DEVICE`` env >
94
+ auto-detect. The env var exists because ``spawn``-based embedding workers
95
+ inherit ``os.environ`` but can't easily receive a Python arg — without a way
96
+ to pin the device, each worker auto-selects MPS and N parallel workers stack
97
+ N GPU allocations into an OOM. So CPU multiprocessing embedding on Apple
98
+ Silicon is only safe with this knob.
99
+
93
100
  :param model_name: HuggingFace model ID or KNOWN_MODELS alias.
101
+ :param device: Explicit device (``"cpu"``/``"mps"``/``"cuda"``). ``None``
102
+ falls back to ``KG_EMBED_DEVICE`` then CUDA→MPS→CPU auto-detect.
94
103
  :return: Loaded ``SentenceTransformer`` instance.
95
104
  """
96
- from sentence_transformers import SentenceTransformer # pylint: disable=import-outside-toplevel
105
+ SentenceTransformer = importlib.import_module("sentence_transformers").SentenceTransformer
97
106
 
98
107
  try:
99
- from transformers import logging as hf_logging # pylint: disable=import-outside-toplevel
108
+ hf_logging = importlib.import_module("transformers.logging")
100
109
 
101
110
  hf_logging.set_verbosity_error()
102
111
  # TQDM_DISABLE alone misses transformers' _tqdm_active gate
@@ -106,9 +115,18 @@ def load_sentence_transformer(model_name: str = DEFAULT_MODEL) -> Any:
106
115
 
107
116
  os.environ["TQDM_DISABLE"] = "1"
108
117
 
109
- import torch # pylint: disable=import-outside-toplevel
110
-
111
- if torch.cuda.is_available():
118
+ torch = importlib.import_module("torch")
119
+
120
+ # Device precedence: explicit arg > KG_EMBED_DEVICE env > auto-detect.
121
+ # The env var lets spawn-based embedding workers (which inherit os.environ
122
+ # but can't easily receive a Python arg) pin to e.g. CPU — without it each
123
+ # worker auto-selects MPS and N parallel workers stack N GPU allocations →
124
+ # MPS OOM. The override is why CPU multiprocessing embedding is safe on
125
+ # Apple Silicon.
126
+ sel = (device or os.environ.get("KG_EMBED_DEVICE", "")).strip().lower()
127
+ if sel:
128
+ device = sel
129
+ elif torch.cuda.is_available():
112
130
  device = "cuda"
113
131
  else:
114
132
  try:
@@ -158,7 +176,7 @@ class SentenceTransformerEmbedder(Embedder):
158
176
 
159
177
  def __init__(self, model_name: str = DEFAULT_MODEL) -> None:
160
178
  try:
161
- from transformers import logging as hf_logging # pylint: disable=import-outside-toplevel
179
+ hf_logging = importlib.import_module("transformers.logging")
162
180
 
163
181
  hf_logging.set_verbosity_error()
164
182
  hf_logging.disable_progress_bar()
@@ -188,7 +206,7 @@ class SentenceTransformerEmbedder(Embedder):
188
206
  :param texts: Input strings.
189
207
  :param encode_batch_size: Passed to ``model.encode()`` — tune down if OOM on MPS.
190
208
  """
191
- import numpy as np # pylint: disable=import-outside-toplevel
209
+ np = importlib.import_module("numpy")
192
210
 
193
211
  vecs = self.model.encode(
194
212
  texts,
@@ -200,7 +218,7 @@ class SentenceTransformerEmbedder(Embedder):
200
218
 
201
219
  def embed_query(self, query: str) -> list[float]:
202
220
  """Embed a single query string into a float32 vector."""
203
- import numpy as np # pylint: disable=import-outside-toplevel
221
+ np = importlib.import_module("numpy")
204
222
 
205
223
  vec = self.model.encode([query], normalize_embeddings=True)[0]
206
224
  return list(np.asarray(vec, dtype="float32").tolist())
@@ -233,7 +251,7 @@ def wrap_embedder(st_model: Any, model_name: str = DEFAULT_MODEL) -> Embedder:
233
251
  :param model_name: Model name stored as metadata on the wrapper.
234
252
  :return: An :class:`Embedder` that delegates all calls to *st_model*.
235
253
  """
236
- import numpy as np # pylint: disable=import-outside-toplevel
254
+ np = importlib.import_module("numpy")
237
255
 
238
256
  resolved = KNOWN_MODELS.get(model_name, model_name)
239
257
  _dim_fn = getattr(st_model, "get_embedding_dimension", None) or getattr(
@@ -4,6 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import base64
7
+ import importlib
7
8
  import random
8
9
  from io import BytesIO
9
10
  from typing import TYPE_CHECKING, Any
@@ -102,7 +103,10 @@ class ImageSynthesizer:
102
103
  def _load_mflux(self, model_name: str) -> Any:
103
104
  if self._mflux_model is not None and self._mflux_model_name == model_name:
104
105
  return self._mflux_model
105
- from mflux.models.flux2.variants.txt2img.flux2_klein import Flux2Klein # type: ignore
106
+
107
+ Flux2Klein = importlib.import_module(
108
+ "mflux.models.flux2.variants.txt2img.flux2_klein"
109
+ ).Flux2Klein
106
110
 
107
111
  self._mflux_model = Flux2Klein(model_path=model_name)
108
112
  self._mflux_model_name = model_name
@@ -98,6 +98,31 @@ class TextSynthesizer:
98
98
  # Public API
99
99
  # ------------------------------------------------------------------
100
100
 
101
+ def complete(
102
+ self,
103
+ messages: list[dict],
104
+ *,
105
+ model: str | None = None,
106
+ max_tokens: int | None = None,
107
+ temperature: float = 0.7,
108
+ ) -> str | None:
109
+ """Run a raw chat completion against the configured backend.
110
+
111
+ General-purpose entry point for callers that build their own message
112
+ list — summarization, classification, arbitrary prompting — rather than
113
+ using :meth:`synthesize_rag` or :meth:`rewrite_for_image`. Applies the
114
+ same oMLX thinking suppression and ``<think>`` stripping as the other
115
+ public methods.
116
+
117
+ :param messages: OpenAI-style chat messages (``[{"role": ..., "content": ...}]``).
118
+ :param model: Override the configured model for this single call.
119
+ :param max_tokens: Override the configured ``max_tokens`` for this call.
120
+ :param temperature: Sampling temperature (lower = more deterministic).
121
+ :returns: The completion text with thinking stripped, or ``None`` on
122
+ failure or empty output.
123
+ """
124
+ return self._complete(messages, model=model, max_tokens=max_tokens, temperature=temperature)
125
+
101
126
  def list_models(self) -> list[str]:
102
127
  """Return the model IDs available at the configured endpoint.
103
128
 
File without changes