langfuse-haystack 0.6.4__tar.gz → 0.7.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 (18) hide show
  1. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/CHANGELOG.md +7 -0
  2. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/PKG-INFO +1 -1
  3. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/pyproject.toml +7 -1
  4. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py +7 -0
  5. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/src/haystack_integrations/tracing/langfuse/tracer.py +5 -1
  6. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/tests/test_tracing.py +25 -1
  7. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/.gitignore +0 -0
  8. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/LICENSE.txt +0 -0
  9. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/README.md +0 -0
  10. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/example/basic_rag.py +0 -0
  11. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/example/chat.py +0 -0
  12. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/example/requirements.txt +0 -0
  13. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/pydoc/config.yml +0 -0
  14. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/src/haystack_integrations/components/connectors/langfuse/__init__.py +0 -0
  15. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/src/haystack_integrations/tracing/langfuse/__init__.py +0 -0
  16. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/tests/__init__.py +0 -0
  17. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/tests/test_langfuse_span.py +0 -0
  18. {langfuse_haystack-0.6.4 → langfuse_haystack-0.7.0}/tests/test_tracer.py +0 -0
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/langfuse-v0.6.4] - 2025-01-17
4
+
5
+ ### 🚀 Features
6
+
7
+ - Add LangfuseConnector secure key management and serialization (#1287)
8
+
9
+
3
10
  ## [integrations/langfuse-v0.6.3] - 2025-01-15
4
11
 
5
12
  ### 🌀 Miscellaneous
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langfuse-haystack
3
- Version: 0.6.4
3
+ Version: 0.7.0
4
4
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme
5
5
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
6
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse
@@ -67,7 +67,12 @@ python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
67
67
  [tool.hatch.envs.lint]
68
68
  installer = "uv"
69
69
  detached = true
70
- dependencies = ["pip", "black>=23.1.0", "mypy>=1.0.0", "ruff>=0.0.243"]
70
+ dependencies = [
71
+ "pip",
72
+ "black>=23.1.0",
73
+ "mypy>=1.0.0",
74
+ "ruff>=0.0.243",
75
+ ]
71
76
 
72
77
  [tool.hatch.envs.lint.scripts]
73
78
  typing = "mypy --install-types --non-interactive --explicit-package-bases {args:src/ tests}"
@@ -167,6 +172,7 @@ module = [
167
172
  "haystack_integrations.*",
168
173
  "pytest.*",
169
174
  "numpy.*",
175
+ "httpx.*",
170
176
  ]
171
177
  ignore_missing_imports = true
172
178
 
@@ -1,5 +1,6 @@
1
1
  from typing import Any, Dict, Optional
2
2
 
3
+ import httpx
3
4
  from haystack import component, default_from_dict, default_to_dict, logging, tracing
4
5
  from haystack.utils import Secret, deserialize_secrets_inplace
5
6
 
@@ -101,6 +102,7 @@ class LangfuseConnector:
101
102
  public: bool = False,
102
103
  public_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_PUBLIC_KEY"), # noqa: B008
103
104
  secret_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
105
+ httpx_client: Optional[httpx.Client] = None,
104
106
  ):
105
107
  """
106
108
  Initialize the LangfuseConnector component.
@@ -112,6 +114,9 @@ class LangfuseConnector:
112
114
  only accessible to the Langfuse account owner. The default is `False`.
113
115
  :param public_key: The Langfuse public key. Defaults to reading from LANGFUSE_PUBLIC_KEY environment variable.
114
116
  :param secret_key: The Langfuse secret key. Defaults to reading from LANGFUSE_SECRET_KEY environment variable.
117
+ :param httpx_client: Optional custom httpx.Client instance to use for Langfuse API calls. Note that when
118
+ deserializing a pipeline from YAML, any custom client is discarded and Langfuse will create its own default
119
+ client, since HTTPX clients cannot be serialized.
115
120
  """
116
121
  self.name = name
117
122
  self.public = public
@@ -121,6 +126,7 @@ class LangfuseConnector:
121
126
  tracer=Langfuse(
122
127
  secret_key=secret_key.resolve_value() if secret_key else None,
123
128
  public_key=public_key.resolve_value() if public_key else None,
129
+ httpx_client=httpx_client,
124
130
  ),
125
131
  name=name,
126
132
  public=public,
@@ -158,6 +164,7 @@ class LangfuseConnector:
158
164
  public=self.public,
159
165
  secret_key=self.secret_key.to_dict() if self.secret_key else None,
160
166
  public_key=self.public_key.to_dict() if self.public_key else None,
167
+ # Note: httpx_client is not serialized as it's not serializable
161
168
  )
162
169
 
163
170
  @classmethod
@@ -201,7 +201,11 @@ class LangfuseTracer(Tracer):
201
201
  )
202
202
 
203
203
  raw_span = span.raw_span()
204
- if isinstance(raw_span, langfuse.client.StatefulSpanClient):
204
+
205
+ # In this section, we finalize both regular spans and generation spans created using the LangfuseSpan class.
206
+ # It's important to end() these spans to ensure they are properly closed and all relevant data is recorded.
207
+ # Note that we do not call end() on the main trace span itself, as its lifecycle is managed differently.
208
+ if isinstance(raw_span, (langfuse.client.StatefulSpanClient, langfuse.client.StatefulGenerationClient)):
205
209
  raw_span.end()
206
210
  self._context.pop()
207
211
 
@@ -10,6 +10,7 @@ from haystack.components.generators.chat import OpenAIChatGenerator
10
10
  from haystack.dataclasses import ChatMessage
11
11
  from haystack.utils import Secret
12
12
  from requests.auth import HTTPBasicAuth
13
+ import httpx
13
14
 
14
15
  from haystack_integrations.components.connectors.langfuse import LangfuseConnector
15
16
  from haystack_integrations.components.generators.anthropic import AnthropicChatGenerator
@@ -49,6 +50,27 @@ def pipeline_with_secrets(llm_class, expected_trace):
49
50
  return pipe
50
51
 
51
52
 
53
+ @pytest.fixture
54
+ def pipeline_with_custom_client(llm_class, expected_trace):
55
+ """Pipeline factory using custom httpx client for Langfuse"""
56
+ pipe = Pipeline()
57
+ custom_client = httpx.Client(timeout=30.0) # Custom timeout of 30 seconds
58
+ pipe.add_component(
59
+ "tracer",
60
+ LangfuseConnector(
61
+ name=f"Chat example - {expected_trace}",
62
+ public=True,
63
+ secret_key=Secret.from_env_var("LANGFUSE_SECRET_KEY"),
64
+ public_key=Secret.from_env_var("LANGFUSE_PUBLIC_KEY"),
65
+ httpx_client=custom_client,
66
+ ),
67
+ )
68
+ pipe.add_component("prompt_builder", ChatPromptBuilder())
69
+ pipe.add_component("llm", llm_class())
70
+ pipe.connect("prompt_builder.prompt", "llm.messages")
71
+ return pipe
72
+
73
+
52
74
  @pytest.mark.integration
53
75
  @pytest.mark.parametrize(
54
76
  "llm_class, env_var, expected_trace",
@@ -58,7 +80,9 @@ def pipeline_with_secrets(llm_class, expected_trace):
58
80
  (CohereChatGenerator, "COHERE_API_KEY", "Cohere"),
59
81
  ],
60
82
  )
61
- @pytest.mark.parametrize("pipeline_fixture", ["pipeline_with_env_vars", "pipeline_with_secrets"])
83
+ @pytest.mark.parametrize(
84
+ "pipeline_fixture", ["pipeline_with_env_vars", "pipeline_with_secrets", "pipeline_with_custom_client"]
85
+ )
62
86
  def test_tracing_integration(llm_class, env_var, expected_trace, pipeline_fixture, request):
63
87
  if not all([os.environ.get("LANGFUSE_SECRET_KEY"), os.environ.get("LANGFUSE_PUBLIC_KEY"), os.environ.get(env_var)]):
64
88
  pytest.skip(f"Missing required environment variables: LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, or {env_var}")