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.
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/CHANGELOG.md +16 -1
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/PKG-INFO +27 -20
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/README.md +26 -19
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py +69 -53
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/tracing/langfuse/tracer.py +3 -2
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/test_langfuse_connector.py +14 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/test_tracing.py +19 -9
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/.gitignore +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/LICENSE.txt +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/basic_rag.py +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/chat.py +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/example/requirements.txt +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/pydoc/config.yml +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/pyproject.toml +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/__init__.py +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/components/connectors/langfuse/__init__.py +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/src/haystack_integrations/tracing/langfuse/__init__.py +0 -0
- {langfuse_haystack-1.1.0 → langfuse_haystack-1.1.2}/tests/__init__.py +0 -0
- {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.
|
|
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
|
[](https://pypi.org/project/langfuse-haystack)
|
|
28
28
|
[](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/).
|
|
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.
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
105
|
+
pipe.connect("prompt_builder.prompt", "llm.messages")
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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".
|
|
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.
|
|
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
|
[](https://pypi.org/project/langfuse-haystack)
|
|
4
4
|
[](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/).
|
|
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.
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
81
|
+
pipe.connect("prompt_builder.prompt", "llm.messages")
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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".
|
|
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.
|
|
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
|
-
|
|
25
|
-
will automatically trace
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"
|
|
93
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|
|
136
|
-
|
|
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
|
|
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
|
-
|
|
181
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|