langfuse-haystack 1.1.0__tar.gz → 1.1.2__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 (19) hide show
  1. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/CHANGELOG.md +16 -1
  2. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/PKG-INFO +27 -20
  3. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/README.md +26 -19
  4. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py +69 -53
  5. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/tracing/langfuse/tracer.py +3 -2
  6. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/test_langfuse_connector.py +14 -0
  7. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/test_tracing.py +19 -9
  8. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/.gitignore +0 -0
  9. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/LICENSE.txt +0 -0
  10. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/basic_rag.py +0 -0
  11. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/chat.py +0 -0
  12. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/requirements.txt +0 -0
  13. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/pydoc/config.yml +0 -0
  14. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/pyproject.toml +0 -0
  15. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/__init__.py +0 -0
  16. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/langfuse/__init__.py +0 -0
  17. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/tracing/langfuse/__init__.py +0 -0
  18. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/__init__.py +0 -0
  19. {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/test_tracer.py +0 -0
@@ -1,11 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/langfuse-v1.1.1] - 2025-05-08
4
+
5
+ ### 🚀 Features
6
+
7
+ - Add more options to LangfuseConnector (#1657)
8
+
9
+
10
+ ## [integrations/langfuse-v1.1.0] - 2025-05-06
11
+
12
+ ### 🚀 Features
13
+
14
+ - Enhance Langfuse ToolInvoker span naming (#1682)
15
+
16
+
3
17
  ## [integrations/langfuse-v1.0.1] - 2025-04-28
4
18
 
5
- ### Bug Fixes
19
+ ### 🐛 Bug Fixes
6
20
 
7
21
  - Langfuse - remove warning "Creating a new trace without a parent span is not recommended"
8
22
 
23
+
9
24
  ## [integrations/langfuse-v1.0.0] - 2025-04-11
10
25
 
11
26
  ### 🐛 Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langfuse-haystack
3
- Version: 1.1.0
3
+ Version: 1.1.2
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
@@ -27,7 +27,10 @@ Description-Content-Type: text/markdown
27
27
  [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
28
28
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
29
29
 
30
- langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/). This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more. Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
30
+ langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/).
31
+ This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more.
32
+ Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
33
+
31
34
  ## Features
32
35
 
33
36
  - Easy integration with Haystack pipelines
@@ -51,7 +54,8 @@ To enable tracing in your Haystack pipeline, add the `LangfuseConnector` to your
51
54
  You also need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order to connect to Langfuse account.
52
55
  You can get these keys by signing up for an account on the Langfuse website.
53
56
 
54
- ⚠️ **Important:** To ensure proper tracing, always set environment variables before importing any Haystack components. This is crucial because Haystack initializes its internal tracing components during import.
57
+ ⚠️ **Important:** To ensure proper tracing, always set environment variables before importing any Haystack components.
58
+ This is crucial because Haystack initializes its internal tracing components during import.
55
59
 
56
60
  Here's the correct way to set up your script:
57
61
 
@@ -93,31 +97,34 @@ from haystack import Pipeline
93
97
 
94
98
  from haystack_integrations.components.connectors.langfuse import LangfuseConnector
95
99
 
96
- if __name__ == "__main__":
97
- pipe = Pipeline()
98
- pipe.add_component("tracer", LangfuseConnector("Chat example"))
99
- pipe.add_component("prompt_builder", ChatPromptBuilder())
100
- pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
100
+ pipe = Pipeline()
101
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
102
+ pipe.add_component("prompt_builder", ChatPromptBuilder())
103
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
101
104
 
102
- pipe.connect("prompt_builder.prompt", "llm.messages")
105
+ pipe.connect("prompt_builder.prompt", "llm.messages")
103
106
 
104
- messages = [
105
- ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
106
- ChatMessage.from_user("Tell me about {{location}}"),
107
- ]
107
+ messages = [
108
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
109
+ ChatMessage.from_user("Tell me about {{location}}"),
110
+ ]
108
111
 
109
- response = pipe.run(
110
- data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "template": messages}}
111
- )
112
- print(response["llm"]["replies"][0])
113
- print(response["tracer"]["trace_url"])
112
+ response = pipe.run(
113
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "template": messages}}
114
+ )
115
+ print(response["llm"]["replies"][0])
116
+ print(response["tracer"]["trace_url"])
117
+ print(response["tracer"]["trace_id"])
114
118
  ```
115
119
 
116
- In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer". Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL. The trace captures the entire execution context, including the prompts, completions, and metadata.
120
+ In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer".
121
+ Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL.
122
+ The trace captures the entire execution context, including the prompts, completions, and metadata.
117
123
 
118
124
  ## Trace Visualization
119
125
 
120
- Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline. Login into your Langfuse account and navigate to the trace URL to view the trace details.
126
+ Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline.
127
+ Login into your Langfuse account and navigate to the trace URL to view the trace details.
121
128
 
122
129
  ## Contributing
123
130
 
@@ -3,7 +3,10 @@
3
3
  [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
4
4
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
5
5
 
6
- langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/). This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more. Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
6
+ langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/).
7
+ This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more.
8
+ Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
9
+
7
10
  ## Features
8
11
 
9
12
  - Easy integration with Haystack pipelines
@@ -27,7 +30,8 @@ To enable tracing in your Haystack pipeline, add the `LangfuseConnector` to your
27
30
  You also need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order to connect to Langfuse account.
28
31
  You can get these keys by signing up for an account on the Langfuse website.
29
32
 
30
- ⚠️ **Important:** To ensure proper tracing, always set environment variables before importing any Haystack components. This is crucial because Haystack initializes its internal tracing components during import.
33
+ ⚠️ **Important:** To ensure proper tracing, always set environment variables before importing any Haystack components.
34
+ This is crucial because Haystack initializes its internal tracing components during import.
31
35
 
32
36
  Here's the correct way to set up your script:
33
37
 
@@ -69,31 +73,34 @@ from haystack import Pipeline
69
73
 
70
74
  from haystack_integrations.components.connectors.langfuse import LangfuseConnector
71
75
 
72
- if __name__ == "__main__":
73
- pipe = Pipeline()
74
- pipe.add_component("tracer", LangfuseConnector("Chat example"))
75
- pipe.add_component("prompt_builder", ChatPromptBuilder())
76
- pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
76
+ pipe = Pipeline()
77
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
78
+ pipe.add_component("prompt_builder", ChatPromptBuilder())
79
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
77
80
 
78
- pipe.connect("prompt_builder.prompt", "llm.messages")
81
+ pipe.connect("prompt_builder.prompt", "llm.messages")
79
82
 
80
- messages = [
81
- ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
82
- ChatMessage.from_user("Tell me about {{location}}"),
83
- ]
83
+ messages = [
84
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
85
+ ChatMessage.from_user("Tell me about {{location}}"),
86
+ ]
84
87
 
85
- response = pipe.run(
86
- data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "template": messages}}
87
- )
88
- print(response["llm"]["replies"][0])
89
- print(response["tracer"]["trace_url"])
88
+ response = pipe.run(
89
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "template": messages}}
90
+ )
91
+ print(response["llm"]["replies"][0])
92
+ print(response["tracer"]["trace_url"])
93
+ print(response["tracer"]["trace_id"])
90
94
  ```
91
95
 
92
- In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer". Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL. The trace captures the entire execution context, including the prompts, completions, and metadata.
96
+ In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer".
97
+ Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL.
98
+ The trace captures the entire execution context, including the prompts, completions, and metadata.
93
99
 
94
100
  ## Trace Visualization
95
101
 
96
- Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline. Login into your Langfuse account and navigate to the trace URL to view the trace details.
102
+ Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline.
103
+ Login into your Langfuse account and navigate to the trace URL to view the trace details.
97
104
 
98
105
  ## Contributing
99
106
 
@@ -21,21 +21,18 @@ class LangfuseConnector:
21
21
  LangfuseConnector connects Haystack LLM framework with [Langfuse](https://langfuse.com) in order to enable the
22
22
  tracing of operations and data flow within various components of a pipeline.
23
23
 
24
- Simply add this component to your pipeline, but *do not* connect it to any other component. The LangfuseConnector
25
- will automatically trace the operations and data flow within the pipeline.
24
+ To use LangfuseConnector, add it to your pipeline without connecting it to any other components.
25
+ It will automatically trace all pipeline operations when tracing is enabled.
26
26
 
27
- Note that you need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order
28
- to use this component. The `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` are the secret and public keys provided
29
- by Langfuse. You can get these keys by signing up for an account on the Langfuse website.
27
+ **Environment Configuration:**
28
+ - `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY`: Required Langfuse API credentials.
29
+ - `HAYSTACK_CONTENT_TRACING_ENABLED`: Must be set to `"true"` to enable tracing.
30
+ - `HAYSTACK_LANGFUSE_ENFORCE_FLUSH`: (Optional) If set to `"false"`, disables flushing after each component.
31
+ Be cautious: this may cause data loss on crashes unless you manually flush before shutdown.
32
+ By default, the data is flushed after each component and blocks the thread until the data is sent to Langfuse.
30
33
 
31
- In addition, you need to set the `HAYSTACK_CONTENT_TRACING_ENABLED` environment variable to `true` in order to
32
- enable Haystack tracing in your pipeline.
33
-
34
- Lastly, you may disable flushing the data after each component by setting the `HAYSTACK_LANGFUSE_ENFORCE_FLUSH`
35
- environment variable to `false`. By default, the data is flushed after each component and blocks the thread until
36
- the data is sent to Langfuse. **Caution**: Disabling this feature may result in data loss if the program crashes
37
- before the data is sent to Langfuse. Make sure you will call langfuse.flush() explicitly before the program exits.
38
- E.g. by using tracer.actual_tracer.flush():
34
+ If you disable flushing after each component make sure you will call langfuse.flush() explicitly before the
35
+ program exits. For example:
39
36
 
40
37
  ```python
41
38
  from haystack.tracing import tracer
@@ -51,13 +48,12 @@ class LangfuseConnector:
51
48
 
52
49
  # ...
53
50
 
54
-
55
51
  @app.on_event("shutdown")
56
52
  async def shutdown_event():
57
53
  tracer.actual_tracer.flush()
58
54
  ```
59
55
 
60
- Here is an example of how to use it:
56
+ Here is an example of how to use LangfuseConnector in a pipeline:
61
57
 
62
58
  ```python
63
59
  import os
@@ -72,37 +68,36 @@ class LangfuseConnector:
72
68
  LangfuseConnector,
73
69
  )
74
70
 
75
- if __name__ == "__main__":
76
- pipe = Pipeline()
77
- pipe.add_component("tracer", LangfuseConnector("Chat example"))
78
- pipe.add_component("prompt_builder", ChatPromptBuilder())
79
- pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
80
-
81
- pipe.connect("prompt_builder.prompt", "llm.messages")
82
-
83
- messages = [
84
- ChatMessage.from_system(
85
- "Always respond in German even if some input data is in other languages."
86
- ),
87
- ChatMessage.from_user("Tell me about {{location}}"),
88
- ]
89
-
90
- response = pipe.run(
91
- data={
92
- "prompt_builder": {
93
- "template_variables": {"location": "Berlin"},
94
- "template": messages,
95
- }
71
+ pipe = Pipeline()
72
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
73
+ pipe.add_component("prompt_builder", ChatPromptBuilder())
74
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-4o-mini"))
75
+
76
+ pipe.connect("prompt_builder.prompt", "llm.messages")
77
+
78
+ messages = [
79
+ ChatMessage.from_system(
80
+ "Always respond in German even if some input data is in other languages."
81
+ ),
82
+ ChatMessage.from_user("Tell me about {{location}}"),
83
+ ]
84
+
85
+ response = pipe.run(
86
+ data={
87
+ "prompt_builder": {
88
+ "template_variables": {"location": "Berlin"},
89
+ "template": messages,
96
90
  }
97
- )
98
- print(response["llm"]["replies"][0])
99
- print(response["tracer"]["trace_url"])
100
- print(response["tracer"]["trace_id"])
91
+ }
92
+ )
93
+ print(response["llm"]["replies"][0])
94
+ print(response["tracer"]["trace_url"])
95
+ print(response["tracer"]["trace_id"])
101
96
  ```
102
97
 
103
- For advanced use cases, you can also customize how spans are created and processed by
104
- providing a custom SpanHandler. This allows you to add custom metrics, set warning levels,
105
- or attach additional metadata to your Langfuse traces:
98
+ For advanced use cases, you can also customize how spans are created and processed by providing a custom
99
+ SpanHandler. This allows you to add custom metrics, set warning levels, or attach additional metadata to your
100
+ Langfuse traces:
106
101
 
107
102
  ```python
108
103
  from haystack_integrations.tracing.langfuse import DefaultSpanHandler, LangfuseSpan
@@ -117,7 +112,6 @@ class LangfuseConnector:
117
112
 
118
113
  connector = LangfuseConnector(span_handler=CustomSpanHandler())
119
114
  ```
120
-
121
115
  """
122
116
 
123
117
  def __init__(
@@ -128,12 +122,15 @@ class LangfuseConnector:
128
122
  secret_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
129
123
  httpx_client: Optional[httpx.Client] = None,
130
124
  span_handler: Optional[SpanHandler] = None,
131
- ):
125
+ *,
126
+ host: Optional[str] = None,
127
+ langfuse_client_kwargs: Optional[Dict[str, Any]] = None,
128
+ ) -> None:
132
129
  """
133
130
  Initialize the LangfuseConnector component.
134
131
 
135
- :param name: The name of the pipeline or component. This name will be used to identify the tracing run on the
136
- Langfuse dashboard.
132
+ :param name: The name for the trace. This name will be used to identify the tracing run in the Langfuse
133
+ dashboard.
137
134
  :param public: Whether the tracing data should be public or private. If set to `True`, the tracing data will be
138
135
  publicly accessible to anyone with the tracing URL. If set to `False`, the tracing data will be private and
139
136
  only accessible to the Langfuse account owner. The default is `False`.
@@ -146,18 +143,28 @@ class LangfuseConnector:
146
143
  The span handler controls how spans are created and processed, allowing customization of span types
147
144
  based on component types and additional processing after spans are yielded. See SpanHandler class for
148
145
  details on implementing custom handlers.
146
+ host: Host of Langfuse API. Can also be set via `LANGFUSE_HOST` environment variable.
147
+ By default it is set to `https://cloud.langfuse.com`.
148
+ :param langfuse_client_kwargs: Optional custom configuration for the Langfuse client. This is a dictionary
149
+ containing any additional configuration options for the Langfuse client. See the Langfuse documentation
150
+ for more details on available configuration options.
149
151
  """
150
152
  self.name = name
151
153
  self.public = public
152
154
  self.secret_key = secret_key
153
155
  self.public_key = public_key
154
156
  self.span_handler = span_handler
157
+ self.host = host
158
+ self.langfuse_client_kwargs = langfuse_client_kwargs
159
+ resolved_langfuse_client_kwargs = {
160
+ "secret_key": secret_key.resolve_value() if secret_key else None,
161
+ "public_key": public_key.resolve_value() if public_key else None,
162
+ "httpx_client": httpx_client,
163
+ "host": host,
164
+ **(langfuse_client_kwargs or {}),
165
+ }
155
166
  self.tracer = LangfuseTracer(
156
- tracer=Langfuse(
157
- secret_key=secret_key.resolve_value() if secret_key else None,
158
- public_key=public_key.resolve_value() if public_key else None,
159
- httpx_client=httpx_client,
160
- ),
167
+ tracer=Langfuse(**resolved_langfuse_client_kwargs),
161
168
  name=name,
162
169
  public=public,
163
170
  span_handler=span_handler,
@@ -165,7 +172,7 @@ class LangfuseConnector:
165
172
  tracing.enable_tracing(self.tracer)
166
173
 
167
174
  @component.output_types(name=str, trace_url=str, trace_id=str)
168
- def run(self, invocation_context: Optional[Dict[str, Any]] = None):
175
+ def run(self, invocation_context: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
169
176
  """
170
177
  Runs the LangfuseConnector component.
171
178
 
@@ -191,6 +198,13 @@ class LangfuseConnector:
191
198
  :returns: The serialized component as a dictionary.
192
199
  """
193
200
  span_handler = serialize_class_instance(self.span_handler) if self.span_handler else None
201
+ if self.langfuse_client_kwargs:
202
+ # pop httpx_client and mask from self._langfuse_client_kwargs to prevent serialization issues
203
+ langfuse_client_kwargs = {
204
+ k: v for k, v in self.langfuse_client_kwargs.items() if k not in ["httpx_client", "mask"]
205
+ }
206
+ else:
207
+ langfuse_client_kwargs = None
194
208
  return default_to_dict(
195
209
  self,
196
210
  name=self.name,
@@ -199,6 +213,8 @@ class LangfuseConnector:
199
213
  public_key=self.public_key.to_dict() if self.public_key else None,
200
214
  # Note: httpx_client is not serialized as it's not serializable
201
215
  span_handler=span_handler,
216
+ host=self.host,
217
+ langfuse_client_kwargs=langfuse_client_kwargs,
202
218
  )
203
219
 
204
220
  @classmethod
@@ -35,6 +35,7 @@ _SUPPORTED_GENERATORS = [
35
35
  "HuggingFaceAPIGenerator",
36
36
  "HuggingFaceLocalGenerator",
37
37
  "CohereGenerator",
38
+ "OllamaGenerator",
38
39
  ]
39
40
  _SUPPORTED_CHAT_GENERATORS = [
40
41
  "AzureOpenAIChatGenerator",
@@ -198,7 +199,7 @@ class SpanHandler(ABC):
198
199
  - Pass your handler to LangfuseConnector init method
199
200
  """
200
201
 
201
- def __init__(self):
202
+ def __init__(self) -> None:
202
203
  self.tracer: Optional[langfuse.Langfuse] = None
203
204
 
204
205
  def init_tracer(self, tracer: langfuse.Langfuse) -> None:
@@ -408,7 +409,7 @@ class LangfuseTracer(Tracer):
408
409
  if self.enforce_flush:
409
410
  self.flush()
410
411
 
411
- def flush(self):
412
+ def flush(self) -> None:
412
413
  self._tracer.flush()
413
414
 
414
415
  def current_span(self) -> Optional[Span]:
@@ -67,6 +67,8 @@ class TestLangfuseConnector:
67
67
  "strict": True,
68
68
  },
69
69
  "span_handler": None,
70
+ "host": None,
71
+ "langfuse_client_kwargs": None,
70
72
  },
71
73
  }
72
74
 
@@ -80,6 +82,8 @@ class TestLangfuseConnector:
80
82
  secret_key=Secret.from_env_var("LANGFUSE_SECRET_KEY"),
81
83
  public_key=Secret.from_env_var("LANGFUSE_PUBLIC_KEY"),
82
84
  span_handler=CustomSpanHandler(),
85
+ host="https://example.com",
86
+ langfuse_client_kwargs={"timeout": 30.0},
83
87
  )
84
88
 
85
89
  serialized = langfuse_connector.to_dict()
@@ -105,6 +109,8 @@ class TestLangfuseConnector:
105
109
  "init_parameters": {},
106
110
  },
107
111
  },
112
+ "host": "https://example.com",
113
+ "langfuse_client_kwargs": {"timeout": 30.0},
108
114
  },
109
115
  }
110
116
 
@@ -128,6 +134,8 @@ class TestLangfuseConnector:
128
134
  "strict": True,
129
135
  },
130
136
  "span_handler": None,
137
+ "host": None,
138
+ "langfuse_client_kwargs": None,
131
139
  },
132
140
  }
133
141
  langfuse_connector = LangfuseConnector.from_dict(data)
@@ -136,6 +144,8 @@ class TestLangfuseConnector:
136
144
  assert langfuse_connector.secret_key == Secret.from_env_var("LANGFUSE_SECRET_KEY")
137
145
  assert langfuse_connector.public_key == Secret.from_env_var("LANGFUSE_PUBLIC_KEY")
138
146
  assert langfuse_connector.span_handler is None
147
+ assert langfuse_connector.host is None
148
+ assert langfuse_connector.langfuse_client_kwargs is None
139
149
 
140
150
  def test_from_dict_with_params(self, monkeypatch):
141
151
  monkeypatch.setenv("LANGFUSE_SECRET_KEY", "secret")
@@ -163,6 +173,8 @@ class TestLangfuseConnector:
163
173
  "init_parameters": {},
164
174
  },
165
175
  },
176
+ "host": "https://example.com",
177
+ "langfuse_client_kwargs": {"timeout": 30.0},
166
178
  },
167
179
  }
168
180
 
@@ -172,6 +184,8 @@ class TestLangfuseConnector:
172
184
  assert langfuse_connector.secret_key == Secret.from_env_var("LANGFUSE_SECRET_KEY")
173
185
  assert langfuse_connector.public_key == Secret.from_env_var("LANGFUSE_PUBLIC_KEY")
174
186
  assert isinstance(langfuse_connector.span_handler, CustomSpanHandler)
187
+ assert langfuse_connector.host == "https://example.com"
188
+ assert langfuse_connector.langfuse_client_kwargs == {"timeout": 30.0}
175
189
 
176
190
  def test_pipeline_serialization(self, monkeypatch):
177
191
  # Set test env vars
@@ -57,6 +57,10 @@ def basic_pipeline(llm_class, expected_trace):
57
57
  return pipe
58
58
 
59
59
 
60
+ @pytest.mark.skipif(
61
+ not all([os.environ.get("LANGFUSE_SECRET_KEY"), os.environ.get("LANGFUSE_PUBLIC_KEY")]),
62
+ reason="Missing required environment variables: LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY",
63
+ )
60
64
  @pytest.mark.integration
61
65
  @pytest.mark.parametrize(
62
66
  "llm_class, env_var, expected_trace",
@@ -68,7 +72,7 @@ def basic_pipeline(llm_class, expected_trace):
68
72
  )
69
73
  def test_tracing_integration(llm_class, env_var, expected_trace, basic_pipeline):
70
74
  if not all([os.environ.get("LANGFUSE_SECRET_KEY"), os.environ.get("LANGFUSE_PUBLIC_KEY"), os.environ.get(env_var)]):
71
- pytest.skip(f"Missing required environment variables: LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, or {env_var}")
75
+ pytest.skip(f"Missing required environment variable: {env_var}")
72
76
 
73
77
  messages = [
74
78
  ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
@@ -102,14 +106,18 @@ def test_tracing_integration(llm_class, env_var, expected_trace, basic_pipeline)
102
106
  assert res_json["observations"][0]["type"] == "GENERATION"
103
107
 
104
108
 
109
+ @pytest.mark.skipif(
110
+ not all(
111
+ [
112
+ os.environ.get("LANGFUSE_SECRET_KEY"),
113
+ os.environ.get("LANGFUSE_PUBLIC_KEY"),
114
+ os.environ.get("OPENAI_API_KEY"),
115
+ ]
116
+ ),
117
+ reason="Missing required environment variables: LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY",
118
+ )
105
119
  @pytest.mark.integration
106
120
  def test_tracing_with_sub_pipelines():
107
- if not all(
108
- [os.environ.get("LANGFUSE_SECRET_KEY"), os.environ.get("LANGFUSE_PUBLIC_KEY"), os.environ.get("OPENAI_API_KEY")]
109
- ):
110
- pytest.skip(
111
- f"Missing required environment variables: LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, or OPENAI_API_KEY"
112
- )
113
121
 
114
122
  @component
115
123
  class SubGenerator:
@@ -177,5 +185,7 @@ def test_tracing_with_sub_pipelines():
177
185
  # There should be two observations for the haystack.pipeline.run span: one for each sub pipeline
178
186
  # Main pipeline is stored under the name "Sub-pipeline example"
179
187
  assert len(haystack_pipeline_run_observations) == 2
180
- assert "prompt_builder" in haystack_pipeline_run_observations[0]["input"]
181
- assert "llm" in haystack_pipeline_run_observations[1]["input"]
188
+ # Apparently the order of haystack_pipeline_run_observations isn't deterministic
189
+ component_names = [key for obs in haystack_pipeline_run_observations for key in obs["input"].keys()]
190
+ assert "prompt_builder" in component_names
191
+ assert "llm" in component_names