langfuse-haystack 3.3.1__tar.gz → 4.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.
Files changed (21) hide show
  1. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/CHANGELOG.md +15 -0
  2. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/PKG-INFO +3 -4
  3. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/pyproject.toml +3 -9
  4. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py +8 -8
  5. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/tracing/langfuse/tracer.py +10 -10
  6. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/tests/test_tracer.py +1 -2
  7. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/.gitignore +0 -0
  8. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/LICENSE.txt +0 -0
  9. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/README.md +0 -0
  10. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/example/basic_rag.py +0 -0
  11. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/example/chat.py +0 -0
  12. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/example/requirements.txt +0 -0
  13. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/pydoc/config_docusaurus.yml +0 -0
  14. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/components/connectors/__init__.py +0 -0
  15. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/components/connectors/langfuse/__init__.py +0 -0
  16. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/components/connectors/py.typed +0 -0
  17. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/tracing/langfuse/__init__.py +0 -0
  18. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/src/haystack_integrations/tracing/py.typed +0 -0
  19. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/tests/__init__.py +0 -0
  20. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/tests/test_langfuse_connector.py +0 -0
  21. {langfuse_haystack-3.3.1 → langfuse_haystack-4.0.0}/tests/test_tracing.py +0 -0
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/langfuse-v3.3.1] - 2025-12-10
4
+
5
+ ### 🚀 Features
6
+
7
+ - *(langfuse)* Add embedder usage metrics for langfuse (#2542)
8
+
9
+ ### 🐛 Bug Fixes
10
+
11
+ - Correct token usage accounting, fix trace polling in tests (#2594)
12
+
13
+ ### 🧹 Chores
14
+
15
+ - Remove Readme API CI workflow and configs (#2573)
16
+
17
+
3
18
  ## [integrations/langfuse-v3.3.0] - 2025-11-21
4
19
 
5
20
  ### 🚀 Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langfuse-haystack
3
- Version: 3.3.1
3
+ Version: 4.0.0
4
4
  Summary: Langfuse integration for Haystack
5
5
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme
6
6
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
@@ -10,15 +10,14 @@ License-Expression: Apache-2.0
10
10
  License-File: LICENSE.txt
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Programming Language :: Python
13
- Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
17
16
  Classifier: Programming Language :: Python :: 3.13
18
17
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
18
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
- Requires-Python: >=3.9
21
- Requires-Dist: haystack-ai>=2.17.1
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: haystack-ai>=2.22.0
22
21
  Requires-Dist: langfuse<4.0.0,>=3.3.1
23
22
  Description-Content-Type: text/markdown
24
23
 
@@ -7,14 +7,13 @@ name = "langfuse-haystack"
7
7
  dynamic = ["version"]
8
8
  description = "Langfuse integration for Haystack"
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" }]
14
14
  classifiers = [
15
15
  "Development Status :: 4 - Beta",
16
16
  "Programming Language :: Python",
17
- "Programming Language :: Python :: 3.9",
18
17
  "Programming Language :: Python :: 3.10",
19
18
  "Programming Language :: Python :: 3.11",
20
19
  "Programming Language :: Python :: 3.12",
@@ -22,7 +21,7 @@ classifiers = [
22
21
  "Programming Language :: Python :: Implementation :: CPython",
23
22
  "Programming Language :: Python :: Implementation :: PyPy",
24
23
  ]
25
- dependencies = ["haystack-ai>=2.17.1", "langfuse>=3.3.1, <4.0.0"]
24
+ dependencies = ["haystack-ai>=2.22.0", "langfuse>=3.3.1, <4.0.0"]
26
25
 
27
26
  [project.urls]
28
27
  Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme"
@@ -47,7 +46,7 @@ dependencies = ["haystack-pydoc-tools", "ruff"]
47
46
 
48
47
  [tool.hatch.envs.default.scripts]
49
48
  docs = ["pydoc-markdown pydoc/config_docusaurus.yml"]
50
- fmt = "ruff check --fix {args} && ruff format {args}"
49
+ fmt = "ruff check --fix {args}; ruff format {args}"
51
50
  fmt-check = "ruff check {args} && ruff format --check {args}"
52
51
 
53
52
  [tool.hatch.envs.test]
@@ -82,7 +81,6 @@ allow-direct-references = true
82
81
 
83
82
 
84
83
  [tool.ruff]
85
- target-version = "py39"
86
84
  line-length = 120
87
85
 
88
86
  [tool.ruff.lint]
@@ -128,10 +126,6 @@ ignore = [
128
126
  # Asserts
129
127
  "S101",
130
128
  ]
131
- unfixable = [
132
- # Don't touch unused imports
133
- "F401",
134
- ]
135
129
 
136
130
  [tool.ruff.lint.isort]
137
131
  known-first-party = ["haystack_integrations"]
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  import httpx
8
8
  from haystack import component, default_from_dict, default_to_dict, logging, tracing
@@ -118,13 +118,13 @@ class LangfuseConnector:
118
118
  self,
119
119
  name: str,
120
120
  public: bool = False,
121
- public_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_PUBLIC_KEY"), # noqa: B008
122
- secret_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
123
- httpx_client: Optional[httpx.Client] = None,
124
- span_handler: Optional[SpanHandler] = None,
121
+ public_key: Secret | None = Secret.from_env_var("LANGFUSE_PUBLIC_KEY"), # noqa: B008
122
+ secret_key: Secret | None = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
123
+ httpx_client: httpx.Client | None = None,
124
+ span_handler: SpanHandler | None = None,
125
125
  *,
126
- host: Optional[str] = None,
127
- langfuse_client_kwargs: Optional[dict[str, Any]] = None,
126
+ host: str | None = None,
127
+ langfuse_client_kwargs: dict[str, Any] | None = None,
128
128
  ) -> None:
129
129
  """
130
130
  Initialize the LangfuseConnector component.
@@ -172,7 +172,7 @@ class LangfuseConnector:
172
172
  tracing.enable_tracing(self.tracer)
173
173
 
174
174
  @component.output_types(name=str, trace_url=str, trace_id=str)
175
- def run(self, invocation_context: Optional[dict[str, Any]] = None) -> dict[str, str]:
175
+ def run(self, invocation_context: dict[str, Any] | None = None) -> dict[str, str]:
176
176
  """
177
177
  Runs the LangfuseConnector component.
178
178
 
@@ -12,7 +12,7 @@ from contextlib import AbstractContextManager
12
12
  from contextvars import ContextVar
13
13
  from dataclasses import dataclass
14
14
  from datetime import datetime
15
- from typing import Any, Literal, Optional, cast
15
+ from typing import Any, Literal, cast
16
16
 
17
17
  from haystack import default_from_dict, default_to_dict, logging
18
18
  from haystack.dataclasses import ChatMessage
@@ -48,7 +48,7 @@ tracing_context_var: ContextVar[dict[Any, Any]] = ContextVar("tracing_context")
48
48
 
49
49
  # Internal span execution hierarchy for our tracer
50
50
  # Manages parent-child relationships and prevents cross-request span interleaving
51
- span_stack_var: ContextVar[Optional[list["LangfuseSpan"]]] = ContextVar("span_stack", default=None)
51
+ span_stack_var: ContextVar[list["LangfuseSpan"] | None] = ContextVar("span_stack", default=None)
52
52
 
53
53
 
54
54
  class LangfuseSpan(Span):
@@ -150,9 +150,9 @@ class SpanContext:
150
150
 
151
151
  name: str
152
152
  operation_name: str
153
- component_type: Optional[str]
153
+ component_type: str | None
154
154
  tags: dict[str, Any]
155
- parent_span: Optional[Span]
155
+ parent_span: Span | None
156
156
  trace_name: str = "Haystack"
157
157
  public: bool = False
158
158
 
@@ -189,7 +189,7 @@ class SpanHandler(ABC):
189
189
  """
190
190
 
191
191
  def __init__(self) -> None:
192
- self.tracer: Optional[langfuse.Langfuse] = None
192
+ self.tracer: langfuse.Langfuse | None = None
193
193
 
194
194
  def init_tracer(self, tracer: langfuse.Langfuse) -> None:
195
195
  """
@@ -215,7 +215,7 @@ class SpanHandler(ABC):
215
215
  pass
216
216
 
217
217
  @abstractmethod
218
- def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
218
+ def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
219
219
  """
220
220
  Process a span after component execution by attaching metadata and metrics.
221
221
 
@@ -338,7 +338,7 @@ class DefaultSpanHandler(SpanHandler):
338
338
  else:
339
339
  return LangfuseSpan(self.tracer.start_as_current_span(name=context.name))
340
340
 
341
- def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
341
+ def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
342
342
  # If the span is at the pipeline level, we add input and output keys to the span
343
343
  at_pipeline_level = span.get_data().get(_PIPELINE_INPUT_KEY) is not None
344
344
  if at_pipeline_level:
@@ -420,7 +420,7 @@ class LangfuseTracer(Tracer):
420
420
  tracer: langfuse.Langfuse,
421
421
  name: str = "Haystack",
422
422
  public: bool = False,
423
- span_handler: Optional[SpanHandler] = None,
423
+ span_handler: SpanHandler | None = None,
424
424
  ) -> None:
425
425
  """
426
426
  Initialize a LangfuseTracer instance.
@@ -450,7 +450,7 @@ class LangfuseTracer(Tracer):
450
450
 
451
451
  @contextlib.contextmanager
452
452
  def trace(
453
- self, operation_name: str, tags: Optional[dict[str, Any]] = None, parent_span: Optional[Span] = None
453
+ self, operation_name: str, tags: dict[str, Any] | None = None, parent_span: Span | None = None
454
454
  ) -> Iterator[Span]:
455
455
  tags = tags or {}
456
456
  span_name = tags.get(_COMPONENT_NAME_KEY, operation_name)
@@ -541,7 +541,7 @@ class LangfuseTracer(Tracer):
541
541
  def flush(self) -> None:
542
542
  self._tracer.flush()
543
543
 
544
- def current_span(self) -> Optional[Span]:
544
+ def current_span(self) -> Span | None:
545
545
  """
546
546
  Return the current active span.
547
547
 
@@ -6,7 +6,6 @@ import asyncio
6
6
  import datetime
7
7
  import logging
8
8
  import sys
9
- from typing import Optional
10
9
  from unittest.mock import MagicMock, Mock, patch
11
10
 
12
11
  import pytest
@@ -107,7 +106,7 @@ class MockLangfuseClient:
107
106
 
108
107
 
109
108
  class CustomSpanHandler(DefaultSpanHandler):
110
- def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
109
+ def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
111
110
  if component_type == "OpenAIChatGenerator":
112
111
  output = span.get_data().get(_COMPONENT_OUTPUT_KEY, {})
113
112
  replies = output.get("replies", [])