@anvia/langfuse 0.6.1 → 1.0.0-rc.10
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.
- package/README.md +120 -448
- package/dist/index.d.ts +83 -46
- package/dist/index.js +786 -632
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# @anvia/langfuse
|
|
2
2
|
|
|
3
|
-
Langfuse tracing
|
|
4
|
-
|
|
5
|
-
Use this package to attach Langfuse tracing to Anvia agents and to publish evaluation scores from Anvia eval reporters.
|
|
3
|
+
Langfuse tracing, evaluation reporting, scoring, prompt, and dataset integration for Anvia.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
@@ -10,506 +8,180 @@ Use this package to attach Langfuse tracing to Anvia agents and to publish evalu
|
|
|
10
8
|
pnpm add @anvia/langfuse @anvia/core
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
## Client lifecycle and Agent tracing
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Usage
|
|
13
|
+
`LangfuseClient` owns its OpenTelemetry SDK, exporter, and optional score queue. Construction and
|
|
14
|
+
accessor calls do not perform I/O; resources are initialized lazily on first use.
|
|
20
15
|
|
|
21
16
|
```ts
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
import { Agent, type CompletionModel } from "@anvia/core";
|
|
18
|
+
import { LangfuseClient } from "@anvia/langfuse";
|
|
19
|
+
|
|
20
|
+
declare const model: CompletionModel;
|
|
21
|
+
|
|
22
|
+
await using langfuse = new LangfuseClient({
|
|
23
|
+
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
24
|
+
secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
25
|
+
baseUrl: process.env.LANGFUSE_BASE_URL,
|
|
26
|
+
serviceName: "support-service",
|
|
27
|
+
environment: "production",
|
|
28
|
+
release: "2026.08.1",
|
|
32
29
|
});
|
|
33
30
|
|
|
34
|
-
const
|
|
35
|
-
|
|
31
|
+
const agent = new Agent({
|
|
32
|
+
id: "support",
|
|
33
|
+
model,
|
|
34
|
+
observability: {
|
|
35
|
+
observers: {
|
|
36
|
+
langfuse: langfuse.observer(),
|
|
37
|
+
},
|
|
38
|
+
primaryTrace: "langfuse",
|
|
39
|
+
errorPolicy: "ignore",
|
|
40
|
+
},
|
|
36
41
|
});
|
|
37
42
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
await tracing.flush();
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Use `flush()` after short-lived jobs. Use `shutdown()` when the process is exiting.
|
|
51
|
-
|
|
52
|
-
## Configuration
|
|
53
|
-
|
|
54
|
-
`langfuse.create()` accepts the following options. Any option that is
|
|
55
|
-
left undefined falls back to the matching environment variable, and
|
|
56
|
-
explicit options always win.
|
|
57
|
-
|
|
58
|
-
| Option | Environment variable | Notes |
|
|
59
|
-
| ------------- | ----------------------------- | ---------------------------------------------------------- |
|
|
60
|
-
| `publicKey` | `LANGFUSE_PUBLIC_KEY` | Required for score publishing. |
|
|
61
|
-
| `secretKey` | `LANGFUSE_SECRET_KEY` | Required for score publishing. |
|
|
62
|
-
| `baseUrl` | `LANGFUSE_BASE_URL` | Defaults to `https://cloud.langfuse.com`. |
|
|
63
|
-
| `environment` | `LANGFUSE_TRACING_ENVIRONMENT`| Tag attached to every trace. |
|
|
64
|
-
| `release` | `LANGFUSE_RELEASE` | Tag attached to every trace. |
|
|
65
|
-
| `serviceName` | `LANGFUSE_SERVICE_NAME` | Recorded on the root observation and as the OTel `service.name` resource attribute. |
|
|
66
|
-
| `captureMode` | — | `"safe"` (default) records instructions/messages plus request summaries; `"full"` includes documents, tool definitions, schemas, and additional parameters. |
|
|
67
|
-
| `captureMaxBytes` | — | Maximum encoded size per captured value; defaults to 262,144 bytes and must be at least 96. |
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
const tracing = langfuse.create({
|
|
71
|
-
// All fields are optional and fall back to env vars.
|
|
72
|
-
serviceName: "support-agent",
|
|
43
|
+
const result = await agent.generate({
|
|
44
|
+
prompt: "Summarize this support request.",
|
|
45
|
+
trace: {
|
|
46
|
+
name: "support-summary",
|
|
47
|
+
userId: "user_123",
|
|
48
|
+
sessionId: "session_456",
|
|
49
|
+
metadata: { tenantId: "acme" },
|
|
50
|
+
tags: ["support"],
|
|
51
|
+
},
|
|
73
52
|
});
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Observation metadata
|
|
77
|
-
|
|
78
|
-
The adapter records structured model and runtime data while keeping
|
|
79
|
-
the default capture surface bounded:
|
|
80
|
-
|
|
81
|
-
- **Generation observations** carry system instructions, model messages,
|
|
82
|
-
the resolved model, and `modelInfo`. Full capture also includes the
|
|
83
|
-
sanitized `providerRequest`.
|
|
84
|
-
`completionStartTime` and `firstDeltaMs` provide native time-to-first-token data.
|
|
85
|
-
- **Usage details** use mutually exclusive `input`, `output`, cache, and
|
|
86
|
-
reasoning buckets so Langfuse can infer cost without double counting.
|
|
87
|
-
- **Generation observations** receive a `generation.update({ output: { delta } })`
|
|
88
|
-
call for every streaming delta (`text_delta`, `reasoning_delta`,
|
|
89
|
-
`tool_call`), so the Langfuse UI reflects partial output as the
|
|
90
|
-
model produces it.
|
|
91
|
-
- **Tool observations** carry arguments on start and structured results on
|
|
92
|
-
end. Definitions and tool metadata are included when `captureMode: "full"`.
|
|
93
|
-
- **Root run observation** carries `serviceName` and the configured
|
|
94
|
-
`metadata` from `AgentRunStartArgs`.
|
|
95
|
-
|
|
96
|
-
Binary and base64 bodies are replaced with omission markers. Oversized
|
|
97
|
-
values are replaced with deterministic bounded previews.
|
|
98
|
-
|
|
99
|
-
## Eval Scores
|
|
100
53
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
54
|
+
if (result.status === "completed") {
|
|
55
|
+
console.log(result.output);
|
|
56
|
+
console.log(result.trace); // { observer: "langfuse", traceId, observationId }
|
|
57
|
+
}
|
|
105
58
|
```
|
|
106
59
|
|
|
107
|
-
|
|
60
|
+
`await using` calls `langfuse[Symbol.asyncDispose]()` at scope exit. Disposal drains queued scores,
|
|
61
|
+
flushes pending traces, and shuts down owned resources. Use `flush()` only when a long-running
|
|
62
|
+
process needs an explicit mid-lifecycle delivery checkpoint. `close()` is idempotent and terminal.
|
|
63
|
+
Each client owns an isolated, unregistered tracer provider, so multiple Langfuse clients and an
|
|
64
|
+
application-wide OpenTelemetry provider can coexist without replacing one another.
|
|
108
65
|
|
|
109
|
-
|
|
66
|
+
Observer capture policy is registration-specific:
|
|
110
67
|
|
|
111
68
|
```ts
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
69
|
+
const observer = langfuse.observer({
|
|
70
|
+
captureMode: "safe",
|
|
71
|
+
captureMaxBytes: 64_000,
|
|
72
|
+
redactInputs: true,
|
|
73
|
+
redactOutputs: "deep",
|
|
74
|
+
redaction: { replacement: "[REDACTED]" },
|
|
118
75
|
});
|
|
119
76
|
```
|
|
120
77
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
not set) drops the score silently. `"warn"` logs a
|
|
124
|
-
`console.warn`. `"throw"` rejects with an error. The legacy
|
|
125
|
-
`strict: true` option continues to work as an alias for
|
|
126
|
-
`"throw"`.
|
|
127
|
-
|
|
128
|
-
- `truncateInputAt` caps the byte size of `caseInputSummary` and
|
|
129
|
-
`caseExpectedSummary` metadata keys. Truncation appends
|
|
130
|
-
`<truncated>` to the cut value.
|
|
131
|
-
|
|
132
|
-
- `includeMessages` controls whether `output.messages` (if present)
|
|
133
|
-
is included in score metadata.
|
|
134
|
-
|
|
135
|
-
- `includeContext` controls whether case `context` and
|
|
136
|
-
`retrievalContext` are included in score metadata. It defaults to
|
|
137
|
-
`false` because retrieved documents may contain sensitive data.
|
|
78
|
+
An observer does not own resources and has no `flush()` or `close()` method. A client can create
|
|
79
|
+
multiple observers with different capture policies.
|
|
138
80
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
The reporter resolves a trace ID for each case in three tiers:
|
|
142
|
-
|
|
143
|
-
1. `output.trace` (most direct, set by an agent run).
|
|
144
|
-
2. `case.input.trace` (useful when the case input bundles trace
|
|
145
|
-
info).
|
|
146
|
-
3. `case.metadata.traceId` (and optional `observationId`).
|
|
147
|
-
|
|
148
|
-
### Metric annotations
|
|
149
|
-
|
|
150
|
-
`EvalMetric` (in `@anvia/core`) accepts optional `dataType`,
|
|
151
|
-
`configId` / `scoreConfigId`, and `metadata` fields. The reporter
|
|
152
|
-
forwards them to Langfuse, so categorical or boolean metrics are
|
|
153
|
-
sent with the right shape:
|
|
81
|
+
## Evaluation reporting
|
|
154
82
|
|
|
155
83
|
```ts
|
|
156
|
-
import {
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
name: "
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
84
|
+
import { agentEvalTarget, contains, runEvalSuite } from "@anvia/core/evals";
|
|
85
|
+
|
|
86
|
+
const suite = await runEvalSuite({
|
|
87
|
+
name: "support-regression",
|
|
88
|
+
cases: [{ id: "refund", input: "What is the refund window?", expected: "30 days" }],
|
|
89
|
+
target: agentEvalTarget<string>({
|
|
90
|
+
agent,
|
|
91
|
+
request: ({ input }) => ({ prompt: input }),
|
|
92
|
+
}),
|
|
93
|
+
metrics: [contains()],
|
|
94
|
+
reporters: [
|
|
95
|
+
langfuse.evalReporter({
|
|
96
|
+
onMissingTrace: "warn",
|
|
97
|
+
includeMessages: false,
|
|
98
|
+
}),
|
|
99
|
+
],
|
|
100
|
+
reporterErrorPolicy: "collect",
|
|
164
101
|
});
|
|
165
102
|
```
|
|
166
103
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
104
|
+
Reporter failures are collected by default. Use `reporterErrorPolicy: "throw"` when reporter
|
|
105
|
+
delivery is operationally required; every reporter is still attempted before the aggregate error
|
|
106
|
+
is thrown. The reporter accepts traces produced by the `"langfuse"` observer by default. When that
|
|
107
|
+
observer has a different Agent registration name, set `traceObserver` to the same name. This
|
|
108
|
+
prevents a score from being posted against another backend's primary trace.
|
|
171
109
|
|
|
172
|
-
|
|
110
|
+
Run an eval suite and publish its cases as one Langfuse dataset experiment:
|
|
173
111
|
|
|
174
112
|
```ts
|
|
175
|
-
await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
113
|
+
const result = await langfuse.runEvalExperiment({
|
|
114
|
+
suite: {
|
|
115
|
+
name: "support-regression",
|
|
116
|
+
cases,
|
|
117
|
+
target,
|
|
118
|
+
metrics,
|
|
119
|
+
},
|
|
120
|
+
experiment: {
|
|
121
|
+
datasetName: "support-cases",
|
|
122
|
+
runName: "rc2",
|
|
123
|
+
publishScores: true,
|
|
124
|
+
},
|
|
183
125
|
});
|
|
184
126
|
```
|
|
185
127
|
|
|
186
|
-
|
|
187
|
-
`langfuse.create({ timeoutMs: ... })`.
|
|
188
|
-
|
|
189
|
-
### Batching and retry (high-volume evals)
|
|
128
|
+
## Scores
|
|
190
129
|
|
|
191
|
-
|
|
192
|
-
`langfuse.create()`. When enabled, `tracing.score()` enqueues the
|
|
193
|
-
score and returns immediately. The queue flushes when it reaches
|
|
194
|
-
`scoreBatchSize`, on a debounce timer (`scoreFlushIntervalMs`,
|
|
195
|
-
default 250 ms), and on `flushScores()`, `flush()`, or `shutdown()`.
|
|
130
|
+
Scores are sent directly unless batching is configured:
|
|
196
131
|
|
|
197
132
|
```ts
|
|
198
|
-
|
|
133
|
+
await using langfuse = new LangfuseClient({
|
|
199
134
|
publicKey,
|
|
200
135
|
secretKey,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
136
|
+
scores: {
|
|
137
|
+
batchSize: 20,
|
|
138
|
+
flushIntervalMs: 250,
|
|
139
|
+
retries: { maxAttempts: 3 },
|
|
140
|
+
},
|
|
204
141
|
});
|
|
205
142
|
|
|
206
|
-
await
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
`flush()` and `shutdown()` also drain the score queue. After all
|
|
213
|
-
retries are exhausted, the queue throws a `LangfuseScoreError` whose
|
|
214
|
-
`scores` property contains the failed payloads so you can inspect
|
|
215
|
-
what was lost.
|
|
216
|
-
|
|
217
|
-
## Event observations & trace handle
|
|
218
|
-
|
|
219
|
-
After a run starts, you can record ad-hoc checkpoints and attach
|
|
220
|
-
extra attributes to the active trace without threading the run
|
|
221
|
-
observer through every function call. The tracing instance exposes
|
|
222
|
-
the most recent trace through `getCurrentTrace()`:
|
|
223
|
-
|
|
224
|
-
```ts
|
|
225
|
-
import { langfuse } from "@anvia/langfuse";
|
|
226
|
-
|
|
227
|
-
const tracing = langfuse.create({ publicKey: "pk", secretKey: "sk" });
|
|
228
|
-
|
|
229
|
-
await tracing.startRun({
|
|
230
|
-
agentName: "support",
|
|
231
|
-
prompt: { role: "user", content: [{ type: "text", text: "hi" }] },
|
|
232
|
-
history: [],
|
|
233
|
-
maxTurns: 3,
|
|
143
|
+
await langfuse.score({
|
|
144
|
+
traceId,
|
|
145
|
+
observationId,
|
|
146
|
+
name: "quality",
|
|
147
|
+
value: 0.95,
|
|
148
|
+
dataType: "NUMERIC",
|
|
234
149
|
});
|
|
235
|
-
|
|
236
|
-
const trace = tracing.getCurrentTrace();
|
|
237
|
-
|
|
238
|
-
trace?.addEvent("retrieval.done", { docCount: 4 });
|
|
239
|
-
trace?.addEvent("validation.passed");
|
|
240
|
-
trace?.addAttributes({ quality: "high" });
|
|
241
150
|
```
|
|
242
151
|
|
|
243
|
-
`
|
|
244
|
-
|
|
245
|
-
observation's metadata. Both calls bubble up to Langfuse via the
|
|
246
|
-
existing OpenTelemetry span processor.
|
|
152
|
+
`maxAttempts` includes the initial attempt. Client disposal drains the queue; callers do not need
|
|
153
|
+
to flush it manually.
|
|
247
154
|
|
|
248
|
-
|
|
249
|
-
use its `event?(...)` hook (added in `@anvia/core`) to record
|
|
250
|
-
checkpoints:
|
|
155
|
+
## Datasets
|
|
251
156
|
|
|
252
157
|
```ts
|
|
253
|
-
const
|
|
254
|
-
agentName: "support",
|
|
255
|
-
prompt: { role: "user", content: [{ type: "text", text: "hi" }] },
|
|
256
|
-
history: [],
|
|
257
|
-
maxTurns: 3,
|
|
258
|
-
});
|
|
158
|
+
const datasets = langfuse.datasetClient({ pageSize: 50 });
|
|
259
159
|
|
|
260
|
-
await
|
|
261
|
-
|
|
262
|
-
|
|
160
|
+
await datasets.createDataset({ name: "support-cases" });
|
|
161
|
+
await datasets.upsertItems({
|
|
162
|
+
name: "support-cases",
|
|
163
|
+
items: [{ id: "refund", input: "Refund window?", expected: "30 days" }],
|
|
263
164
|
});
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
The trace handle is cleared when the run `end`s or `error`s. If you
|
|
267
|
-
call `addEvent` or `addAttributes` after that, the underlying
|
|
268
|
-
Langfuse SDK will reject the call because the root observation is
|
|
269
|
-
no longer accepting children. We let the error propagate so it is
|
|
270
|
-
visible.
|
|
271
|
-
|
|
272
|
-
`getCurrentTrace()` is per-tracing-instance and last-write-wins:
|
|
273
|
-
when multiple runs start on the same instance, the handle always
|
|
274
|
-
points at the most recent run. For true concurrency, manage your
|
|
275
|
-
own context (e.g. capture the run observer or build your own
|
|
276
|
-
mapping keyed on user/session).
|
|
277
165
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
Bridge `@anvia/core/evals` to Langfuse's dataset / experiment-run
|
|
281
|
-
workflow. The dataset client surfaces the four endpoints you need
|
|
282
|
-
to create a dataset, fetch its items, upsert items, and post a
|
|
283
|
-
batched dataset-run-items payload.
|
|
284
|
-
|
|
285
|
-
```ts
|
|
286
|
-
import {
|
|
287
|
-
createLangfuseDatasetClient,
|
|
288
|
-
runEvalAsExperiment,
|
|
289
|
-
langfuse,
|
|
290
|
-
} from "@anvia/langfuse";
|
|
291
|
-
|
|
292
|
-
const tracing = langfuse.create({ publicKey: "pk", secretKey: "sk" });
|
|
293
|
-
const client = createLangfuseDatasetClient(tracing);
|
|
294
|
-
|
|
295
|
-
await client.createDataset({ name: "support-smoke" });
|
|
296
|
-
await client.upsertItems("support-smoke", [
|
|
297
|
-
{ id: "c-1", input: { q: "hi" }, expected: "hello" },
|
|
298
|
-
{ id: "c-2", input: { q: "bye" } },
|
|
299
|
-
]);
|
|
300
|
-
|
|
301
|
-
const dataset = await client.getDataset("support-smoke");
|
|
302
|
-
console.log(dataset.items);
|
|
303
|
-
|
|
304
|
-
await client.runExperiment({
|
|
305
|
-
datasetName: "support-smoke",
|
|
306
|
-
runName: "smoke-2026-06",
|
|
307
|
-
run: (item) => ({
|
|
308
|
-
output: `answer-for-${item.id}`,
|
|
309
|
-
trace: { traceId: `trace-${item.id}` },
|
|
310
|
-
}),
|
|
166
|
+
const dataset = await datasets.getDataset<string, string>({
|
|
167
|
+
name: "support-cases",
|
|
311
168
|
});
|
|
312
169
|
```
|
|
313
170
|
|
|
314
|
-
|
|
315
|
-
dataset run alongside the metric scores:
|
|
171
|
+
## Prompts
|
|
316
172
|
|
|
317
173
|
```ts
|
|
318
|
-
|
|
319
|
-
import { runEvalAsExperiment } from "@anvia/langfuse";
|
|
320
|
-
|
|
321
|
-
const { suite, datasetRun } = await runEvalAsExperiment(
|
|
322
|
-
{
|
|
323
|
-
name: "smoke",
|
|
324
|
-
cases: [
|
|
325
|
-
{ id: "c-1", input: "a", expected: "A" },
|
|
326
|
-
{ id: "c-2", input: "b", expected: "B" },
|
|
327
|
-
],
|
|
328
|
-
target: agentEvalTarget(supportAgent),
|
|
329
|
-
metrics: [/* ... */],
|
|
330
|
-
reporters: [/* existing reporters still score */],
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
tracing,
|
|
334
|
-
datasetName: "smoke-set",
|
|
335
|
-
runName: "smoke-run",
|
|
336
|
-
publishScores: true,
|
|
337
|
-
reporterOptions: { onMissingTrace: "warn" },
|
|
338
|
-
},
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
console.log(suite.metrics.passed, datasetRun.posted);
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
`publishScores` adds a Langfuse eval reporter without replacing reporters
|
|
345
|
-
already configured on the suite. `agentEvalTarget(...)` returns the response trace used to attach
|
|
346
|
-
each score. Set `includeContexts: true` only when case context may be persisted in Langfuse dataset
|
|
347
|
-
metadata.
|
|
348
|
-
|
|
349
|
-
### Options
|
|
350
|
-
|
|
351
|
-
- `createLangfuseDatasetClient(tracing, options)`:
|
|
352
|
-
- `publicKey`, `secretKey`, `baseUrl`: optionally override the
|
|
353
|
-
tracing instance's resolved values. Falls back to env vars
|
|
354
|
-
(`LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_BASE_URL`).
|
|
355
|
-
- `pageSize` (default `50`): dataset item pagination.
|
|
356
|
-
- `timeoutMs` (default `30_000`): per-request timeout via
|
|
357
|
-
`AbortSignal.timeout`.
|
|
358
|
-
- `client.runExperiment({ ... })`:
|
|
359
|
-
- `items` (optional): supply items directly to skip the
|
|
360
|
-
`getDataset` round trip.
|
|
361
|
-
- `run`: invoked per item, returns `{ output, trace? }`.
|
|
362
|
-
Per-item failures are caught and surfaced in the result's
|
|
363
|
-
`errors` array; only successful items reach the batched POST.
|
|
364
|
-
|
|
365
|
-
### Failure handling
|
|
366
|
-
|
|
367
|
-
`runExperiment` continues on per-item errors. The `errors` array
|
|
368
|
-
contains `{ itemId, error }` entries for failed items; the POST
|
|
369
|
-
still goes out with the successful subset. Non-2xx on the
|
|
370
|
-
batched POST throws (and the items that already errored are
|
|
371
|
-
also included in the thrown error's context).
|
|
372
|
-
|
|
373
|
-
## Prompt management
|
|
374
|
-
|
|
375
|
-
Pull prompts from Langfuse's prompt store and link generations to
|
|
376
|
-
the prompt version. The tracing instance attaches the prompt name
|
|
377
|
-
and version to the root trace and every generation in the run
|
|
378
|
-
when a prompt ref is configured.
|
|
379
|
-
|
|
380
|
-
```ts
|
|
381
|
-
import { createLangfusePromptClient, langfuse } from "@anvia/langfuse";
|
|
382
|
-
|
|
383
|
-
const tracing = langfuse.create({ publicKey: "pk", secretKey: "sk" });
|
|
384
|
-
const prompts = createLangfusePromptClient(tracing);
|
|
385
|
-
|
|
386
|
-
const prompt = await prompts.getPrompt("support.system");
|
|
387
|
-
console.log(prompt.prompt, prompt.version);
|
|
388
|
-
|
|
389
|
-
await agent
|
|
390
|
-
.prompt("hi")
|
|
391
|
-
.withTrace({
|
|
392
|
-
promptRef: { name: "support.system", version: prompt.version },
|
|
393
|
-
})
|
|
394
|
-
.send();
|
|
395
|
-
```
|
|
174
|
+
const prompts = langfuse.promptClient({ cacheTtlMs: 60_000 });
|
|
396
175
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
### Prompt client options
|
|
402
|
-
|
|
403
|
-
- `cacheTtlMs` (default `60_000`): in-memory TTL per
|
|
404
|
-
`${name}::${version}::${label}` key.
|
|
405
|
-
- `timeoutMs` (default `30_000`): per-request timeout via
|
|
406
|
-
`AbortSignal.timeout`.
|
|
407
|
-
- `publicKey`, `secretKey`, `baseUrl`: override the tracing
|
|
408
|
-
instance's resolved values, falling back to env vars.
|
|
409
|
-
|
|
410
|
-
### Per-call options
|
|
411
|
-
|
|
412
|
-
- `getPrompt(name, { version?, label?, cacheTtlMs?, refresh? })`:
|
|
413
|
-
- `version` and `label` filter the upstream request.
|
|
414
|
-
- `cacheTtlMs` overrides the client default for this call.
|
|
415
|
-
- `refresh: true` skips the cache and re-fetches.
|
|
416
|
-
|
|
417
|
-
### Helpers
|
|
418
|
-
|
|
419
|
-
- `getPromptText(name, options?)`: returns the prompt string;
|
|
420
|
-
throws if the prompt is a chat prompt.
|
|
421
|
-
- `getPromptChat(name, options?)`: returns the chat message
|
|
422
|
-
array; throws if the prompt is a text prompt.
|
|
423
|
-
- `refresh()`: clears the cache.
|
|
424
|
-
|
|
425
|
-
## PII redaction
|
|
426
|
-
|
|
427
|
-
Mask personally identifiable information in observations before it
|
|
428
|
-
leaves the process. The default pattern set catches emails,
|
|
429
|
-
credit cards (with Luhn validation), phone numbers, IPv4
|
|
430
|
-
addresses, JWTs, and common API key shapes.
|
|
431
|
-
|
|
432
|
-
```ts
|
|
433
|
-
import { langfuse } from "@anvia/langfuse";
|
|
434
|
-
|
|
435
|
-
const tracing = langfuse.create({
|
|
436
|
-
publicKey: "pk",
|
|
437
|
-
secretKey: "sk",
|
|
438
|
-
redactInputs: true,
|
|
439
|
-
redactOutputs: "deep",
|
|
176
|
+
const text = await prompts.getPromptText({
|
|
177
|
+
name: "support.system",
|
|
178
|
+
label: "production",
|
|
440
179
|
});
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
- `redactInputs` redacts system instructions, root inputs, chat history,
|
|
444
|
-
tool arguments, request metadata, and nested-agent inputs.
|
|
445
|
-
- `redactOutputs` redacts streaming/final generation output, errors,
|
|
446
|
-
tool results, transcripts, and nested-agent outputs.
|
|
447
|
-
- `"deep"` recurses into nested objects and arrays (in addition to
|
|
448
|
-
top-level strings).
|
|
449
|
-
|
|
450
|
-
### Customizing
|
|
451
|
-
|
|
452
|
-
```ts
|
|
453
|
-
const tracing = langfuse.create({
|
|
454
|
-
publicKey: "pk",
|
|
455
|
-
secretKey: "sk",
|
|
456
|
-
redactOutputs: true,
|
|
457
|
-
redaction: {
|
|
458
|
-
replacement: "[HIDDEN]",
|
|
459
|
-
patterns: [
|
|
460
|
-
{ name: "ssn", regex: /\b\d{3}-\d{2}-\d{4}\b/g },
|
|
461
|
-
],
|
|
462
|
-
},
|
|
463
|
-
});
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
`createPiiRedactor(options)` is also exported for ad-hoc use:
|
|
467
180
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const redactor = createPiiRedactor();
|
|
472
|
-
const safe = redactor.redactString("email alice@example.com today");
|
|
473
|
-
const safeMessages = redactor.redactMessages(messages);
|
|
474
|
-
const safeObject = redactor.redactObject(spanInput);
|
|
181
|
+
const chat = await prompts.getPromptChat({ name: "support.chat" });
|
|
182
|
+
prompts.refresh();
|
|
475
183
|
```
|
|
476
184
|
|
|
477
|
-
## Exports
|
|
478
|
-
|
|
479
|
-
- `langfuse`
|
|
480
|
-
- `createLangfuseDatasetClient`
|
|
481
|
-
- `createLangfuseEvalReporter`
|
|
482
|
-
- `createLangfusePromptClient`
|
|
483
|
-
- `runEvalAsExperiment`
|
|
484
|
-
- `LangfuseScoreError`
|
|
485
|
-
- `LangfuseTracing`
|
|
486
|
-
- `LangfuseTraceHandle`
|
|
487
|
-
- `LangfuseTracingOptions`
|
|
488
|
-
- `LangfuseScoreArgs`
|
|
489
|
-
- `LangfuseScoreDataType`
|
|
490
|
-
- `LangfuseEvalReporterOptions`
|
|
491
|
-
- `LangfuseDatasetClient`
|
|
492
|
-
- `LangfuseDatasetClientOptions`
|
|
493
|
-
- `LangfuseDataset`
|
|
494
|
-
- `LangfuseDatasetItem`
|
|
495
|
-
- `LangfuseRunExperimentOptions`
|
|
496
|
-
- `LangfuseRunExperimentResult`
|
|
497
|
-
- `LangfuseRunItemResult`
|
|
498
|
-
- `LangfuseRunItemError`
|
|
499
|
-
- `LangfusePromptClient`
|
|
500
|
-
- `LangfusePromptClientOptions`
|
|
501
|
-
- `LangfusePromptGetOptions`
|
|
502
|
-
- `LangfusePrompt`
|
|
503
|
-
- `LangfuseChatMessage`
|
|
504
|
-
- `RunEvalAsExperimentOptions`
|
|
505
|
-
- `RunEvalAsExperimentResult`
|
|
506
|
-
- `createPiiRedactor`
|
|
507
|
-
- `DEFAULT_PATTERNS`
|
|
508
|
-
- `PiiRedactor`
|
|
509
|
-
- `RedactorPattern`
|
|
510
|
-
- `LangfuseRedactionOptions`
|
|
511
|
-
- `LangfuseRedactionMode`
|
|
512
|
-
|
|
513
185
|
## Development
|
|
514
186
|
|
|
515
187
|
```sh
|