@insightfactory.ai/insightfactory-databricks-langgraph-tracer 1.0.0-dev.0
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/CHANGELOG.md +176 -0
- package/LICENSE +5 -0
- package/README.md +160 -0
- package/THIRD_PARTY_NOTICES +26 -0
- package/dist/cost.d.ts +76 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +124 -0
- package/dist/cost.js.map +1 -0
- package/dist/databricks-tracer.d.ts +235 -0
- package/dist/databricks-tracer.d.ts.map +1 -0
- package/dist/databricks-tracer.js +841 -0
- package/dist/databricks-tracer.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +8 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated-keys.d.ts +39 -0
- package/dist/generated-keys.d.ts.map +1 -0
- package/dist/generated-keys.js +39 -0
- package/dist/generated-keys.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/pricing/model-pricing-overrides.json +28 -0
- package/dist/pricing/model-pricing.json +1 -0
- package/dist/token-aggregate.d.ts +29 -0
- package/dist/token-aggregate.d.ts.map +1 -0
- package/dist/token-aggregate.js +63 -0
- package/dist/token-aggregate.js.map +1 -0
- package/dist/trace-metadata.d.ts +14 -0
- package/dist/trace-metadata.d.ts.map +1 -0
- package/dist/trace-metadata.js +33 -0
- package/dist/trace-metadata.js.map +1 -0
- package/dist/uc-export.d.ts +48 -0
- package/dist/uc-export.d.ts.map +1 -0
- package/dist/uc-export.js +243 -0
- package/dist/uc-export.js.map +1 -0
- package/package.json +68 -0
- package/src/pricing/model-pricing-overrides.json +28 -0
- package/src/pricing/model-pricing.json +1 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom LangChain `BaseTracer` that emits the shared schema to Databricks
|
|
3
|
+
* MLflow via `@mlflow/core`.
|
|
4
|
+
*
|
|
5
|
+
* This is the TypeScript counterpart of the Python `DatabricksLangGraphTracer`
|
|
6
|
+
* and emits the **identical** shared trace/span schema
|
|
7
|
+
* (`schema/trace-schema.json`):
|
|
8
|
+
*
|
|
9
|
+
* - **Root run create** → trace **tags** (`source`, `langgraph.run_id` /
|
|
10
|
+
* `graph_id` / `env` / `api_revision`, conditional `langgraph.thread_id`) and
|
|
11
|
+
* trace **metadata** (`mlflow.trace.session` / `mlflow.trace.user` when a
|
|
12
|
+
* thread / user is present).
|
|
13
|
+
* - **Child run create** → `langgraph.node` / `langgraph.step` on the live node
|
|
14
|
+
* span (from LangGraph's run metadata).
|
|
15
|
+
* - **LLM run update (end)** → resolved `mlflow.llm.model` / `mlflow.llm.provider`,
|
|
16
|
+
* the reserved `mlflow.chat.tokenUsage` (incl. the cache-read / cache-creation
|
|
17
|
+
* slots), the non-reserved token-count attrs, the reserved 3-key
|
|
18
|
+
* `mlflow.llm.cost` plus the non-reserved cache cost line-items, and the
|
|
19
|
+
* OpenInference-style `llm.*` dashboard keys (`llm.model_name` /
|
|
20
|
+
* `llm.model_provider` / `llm.usage.prompt_tokens_cost` /
|
|
21
|
+
* `llm.usage.completion_tokens_cost` — the keys the Databricks experiment
|
|
22
|
+
* Overview cost charts aggregate) — accumulating a per-root cost aggregate
|
|
23
|
+
* (totals **and** a per-model cost/token rollup).
|
|
24
|
+
* - **Root run update (end), before `span.end()`** → the reserved 3-key
|
|
25
|
+
* `mlflow.trace.cost` metadata rollup, the per-model `cost.by_model` tag
|
|
26
|
+
* (JSON), and the `cost.unknown_model` tag.
|
|
27
|
+
*
|
|
28
|
+
* Uses `startSpan` with an explicit `parent` ({@link LiveSpan}) so nested runs
|
|
29
|
+
* keep hierarchy without relying on the OTEL active context (callbacks are not
|
|
30
|
+
* executed inside `withSpan`). {@link BaseTracer} invokes `persistRun` only for
|
|
31
|
+
* root runs; every run (root included) is closed from `onRunUpdate`.
|
|
32
|
+
*/
|
|
33
|
+
import { SpanType } from "@mlflow/core";
|
|
34
|
+
import { BaseTracer, type Run } from "@langchain/core/tracers/base";
|
|
35
|
+
import { type TokenUsage } from "./cost.js";
|
|
36
|
+
/** Maps LangChain `run_type` strings to MLflow {@link SpanType} (default CHAIN). */
|
|
37
|
+
export declare function mapLangChainRunTypeToMlflowSpanType(runType: string): SpanType;
|
|
38
|
+
/** Best-effort JSON-serializable copy for span inputs/outputs (handles cycles). */
|
|
39
|
+
export declare function serializeTracePayload(value: unknown): unknown;
|
|
40
|
+
/**
|
|
41
|
+
* Multimodal content-reference externalization (issues #16, #21). Chat-model span
|
|
42
|
+
* inputs preserve multimodal image / PDF / file content parts, but the inline
|
|
43
|
+
* base64 payload of each is removed before recording: the part is replaced with a
|
|
44
|
+
* lightweight reference so the Unity Catalog trace tables never carry the multi-MB
|
|
45
|
+
* data URIs that pushed large invoice traces past the SQL inline read limit.
|
|
46
|
+
*
|
|
47
|
+
* By default a part becomes a `{ type, _omitted: true, bytes: N }` placeholder. A
|
|
48
|
+
* consumer can instead supply a {@link ContentRefResolver} mapping a part to its
|
|
49
|
+
* own reference object — for example, the Unity Catalog volume path the image
|
|
50
|
+
* was loaded from, so the original can be re-fetched at runtime. The resolver runs
|
|
51
|
+
* only on the stored copy of the inputs; the live message sent to the model is
|
|
52
|
+
* untouched (so prompt caching is unaffected).
|
|
53
|
+
*
|
|
54
|
+
* When `maxStringChars` is set, any over-long *plain-text* leaf — in span **inputs or
|
|
55
|
+
* outputs** — is replaced with a compact `{ _truncated: true, chars: N, bytes: M,
|
|
56
|
+
* preview: "…" }` placeholder before recording: large text, not just multimodal
|
|
57
|
+
* bytes, can also push a trace past the SQL inline read limit. The
|
|
58
|
+
* multimodal payload externalization above runs on inputs only (LLM messages);
|
|
59
|
+
* outputs are arbitrary chain / tool JSON, so only the text cap is applied to them
|
|
60
|
+
* (see {@link externalizeContentRefs}). Both run on a copy; the live values are never
|
|
61
|
+
* mutated.
|
|
62
|
+
*/
|
|
63
|
+
/** Context passed to a {@link ContentRefResolver} for one multimodal part. */
|
|
64
|
+
export interface ContentPartContext {
|
|
65
|
+
/** Position within the message `content` array (the page number for a pure-image message). */
|
|
66
|
+
index: number;
|
|
67
|
+
/** Encoded length of the inline payload being externalized. */
|
|
68
|
+
bytes: number;
|
|
69
|
+
/**
|
|
70
|
+
* The run's metadata (`run.extra.metadata` — LangGraph / RunnableConfig metadata).
|
|
71
|
+
* This is a **shallow copy** of the run metadata, so adding or replacing top-level
|
|
72
|
+
* keys is harmless (it cannot corrupt the live run state shared with sibling/child
|
|
73
|
+
* spans); its nested values are still shared, so do not mutate those.
|
|
74
|
+
*/
|
|
75
|
+
metadata: Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Consumer hook: maps a multimodal content part (+ its context) to the reference
|
|
79
|
+
* object stored in the trace, or `undefined` / `null` to fall back to the default
|
|
80
|
+
* `{ type, _omitted: true, bytes: N }` placeholder.
|
|
81
|
+
*/
|
|
82
|
+
export type ContentRefResolver = (part: Record<string, unknown>, ctx: ContentPartContext) => Record<string, unknown> | undefined | null;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the text cap: explicit option wins, else `DATABRICKS_TRACING_MAX_STRING_CHARS`.
|
|
85
|
+
* Returns `undefined` (cap disabled) when neither is set, or when the value is not a
|
|
86
|
+
* positive integer. A non-positive / unparseable env value is ignored (warned), not
|
|
87
|
+
* thrown, so a stray override never breaks tracing startup.
|
|
88
|
+
*/
|
|
89
|
+
export declare function resolveMaxStringChars(explicit?: number): number | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Externalize multimodal content parts' inline payloads and cap text.
|
|
92
|
+
* Public entry point. Takes a **shallow copy** of `metadata` once (when payloads are
|
|
93
|
+
* externalized with a resolver) so a resolver mutating `ctx.metadata` cannot corrupt
|
|
94
|
+
* the live run metadata, which the caller passes by reference and which is shared with
|
|
95
|
+
* sibling / child spans (resilient by design — a faulty resolver must not affect
|
|
96
|
+
* tracing). Then walks via {@link externalizeWalk}.
|
|
97
|
+
*
|
|
98
|
+
* `externalizePayloads` controls the multimodal-part stripping:
|
|
99
|
+
* - **inputs** (`true`) — the #21 behaviour: inline image / PDF / file payloads in
|
|
100
|
+
* message `content` arrays are replaced with references (inputs are LLM messages,
|
|
101
|
+
* where the `content` / `data` / `base64` shapes are genuinely multimodal).
|
|
102
|
+
* - **outputs** (`false`) — only the text cap is applied. Span outputs are arbitrary
|
|
103
|
+
* chain / tool return values; the multimodal probe matches a bare `data` / `base64`
|
|
104
|
+
* string in any `content` list, so running it would strip legitimate non-binary
|
|
105
|
+
* output to an `_omitted` placeholder. A genuinely huge inline payload in an output
|
|
106
|
+
* is still bounded by the text cap when it is set.
|
|
107
|
+
*/
|
|
108
|
+
export declare function externalizeContentRefs(obj: unknown, resolver: ContentRefResolver | undefined, metadata: Record<string, unknown>, maxStringChars?: number, externalizePayloads?: boolean): unknown;
|
|
109
|
+
/**
|
|
110
|
+
* Extract normalized token usage from an LLM run end payload, extended for the
|
|
111
|
+
* Anthropic `cache_creation` category to match the Python `_extract_usage`.
|
|
112
|
+
*
|
|
113
|
+
* Prefers LangChain normalized `usage_metadata`
|
|
114
|
+
* (`input_token_details.cache_read` / `.cache_creation`,
|
|
115
|
+
* `output_token_details.reasoning`); falls back to raw `response_metadata.usage`
|
|
116
|
+
* (`input_tokens_details.cached_tokens` / `cache_read_input_tokens`,
|
|
117
|
+
* `cache_creation_input_tokens`, `output_tokens_details.reasoning_tokens`).
|
|
118
|
+
* Missing cache/reasoning sub-fields default to `0`. Returns `undefined` when
|
|
119
|
+
* neither source is present.
|
|
120
|
+
*/
|
|
121
|
+
export declare function extractUsage(run: Run): TokenUsage | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Derive the canonical LiteLLM catalog key for an LLM run, aligned with the
|
|
124
|
+
* Python `_extract_model`.
|
|
125
|
+
*
|
|
126
|
+
* Sources, in order: invocation params `model` (probed both top-level on
|
|
127
|
+
* `run.extra.invocation_params` and nested under `run.extra.metadata`), then
|
|
128
|
+
* `response_metadata.model_name` — each qualified via `qualify` (default
|
|
129
|
+
* {@link qualifyDeploymentName}; consumers with non-canonical deployment
|
|
130
|
+
* names supply a resolver via the tracer's `pricingKeyResolver` option).
|
|
131
|
+
*/
|
|
132
|
+
export declare function extractModel(run: Run, qualify?: (name: string) => string): string | undefined;
|
|
133
|
+
export declare class DatabricksLangGraphTracer extends BaseTracer {
|
|
134
|
+
name: string;
|
|
135
|
+
private readonly source;
|
|
136
|
+
private readonly qualifyModel;
|
|
137
|
+
private readonly contentRefResolver;
|
|
138
|
+
private readonly maxStringChars;
|
|
139
|
+
private readonly spanMap;
|
|
140
|
+
private readonly traceAggregates;
|
|
141
|
+
private readonly rootByRunId;
|
|
142
|
+
constructor(options?: {
|
|
143
|
+
source?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Maps a deployment/model name to its LiteLLM catalog key, for
|
|
146
|
+
* deployments whose names diverge from the catalog (e.g. a tenant
|
|
147
|
+
* alias, or third-party models like `kimi-*` priced under another
|
|
148
|
+
* provider). Return `undefined` to fall through to the default
|
|
149
|
+
* `azure/<name>` → `azure_ai/<name>` probe.
|
|
150
|
+
*/
|
|
151
|
+
pricingKeyResolver?: (name: string) => string | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Maps each multimodal content part to the reference stored in the trace in
|
|
154
|
+
* place of its inline base64 (issues #16/#21). When omitted, parts are
|
|
155
|
+
* externalized to a `{ type, _omitted: true, bytes: N }` placeholder. Runs on
|
|
156
|
+
* a copy of the inputs only — the live message sent to the model is untouched.
|
|
157
|
+
*/
|
|
158
|
+
contentRefResolver?: ContentRefResolver;
|
|
159
|
+
/**
|
|
160
|
+
* Opt into capping over-long *plain-text* leaves in span inputs / outputs to a
|
|
161
|
+
* `{ _truncated: true, … }` placeholder (large text, not just
|
|
162
|
+
* multimodal bytes, can push a trace past the SQL inline read limit). Falls
|
|
163
|
+
* back to `DATABRICKS_TRACING_MAX_STRING_CHARS`, else off. A distinct knob from
|
|
164
|
+
* the multimodal reference handling above.
|
|
165
|
+
*/
|
|
166
|
+
maxStringChars?: number;
|
|
167
|
+
});
|
|
168
|
+
onRunCreate(run: Run): Promise<void>;
|
|
169
|
+
onRunUpdate(run: Run): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Write the root trace tags + session/user metadata (Python
|
|
172
|
+
* `_write_root_trace_fields`). Always emits `source` + the `langgraph.run_id` /
|
|
173
|
+
* `graph_id` / `env` / `api_revision` tags. A thread id additionally produces
|
|
174
|
+
* the `langgraph.thread_id` tag and the reserved `mlflow.trace.session`
|
|
175
|
+
* metadata; a user identity produces the reserved `mlflow.trace.user` metadata.
|
|
176
|
+
*/
|
|
177
|
+
private writeRootTraceFields;
|
|
178
|
+
/**
|
|
179
|
+
* Write `langgraph.node` / `langgraph.step` onto a child span. LangGraph stamps
|
|
180
|
+
* these onto every per-node run's metadata (including the node's nested LLM
|
|
181
|
+
* run), mirroring the Python `_write_child_langgraph_context`.
|
|
182
|
+
*/
|
|
183
|
+
private writeChildLangGraphContext;
|
|
184
|
+
/**
|
|
185
|
+
* Write model / provider / token-usage / cost attrs on a live LLM span (Python
|
|
186
|
+
* `_enrich_llm_span`). Token usage is written whenever usage is extractable;
|
|
187
|
+
* model / provider whenever the model resolves. Cost needs both: the reserved
|
|
188
|
+
* 3-key `mlflow.llm.cost` plus the non-reserved cache-read / cache-creation
|
|
189
|
+
* cost line-items (Option B) are written and folded into the root aggregate; a
|
|
190
|
+
* resolved-but-unpriceable model is recorded for the `cost.unknown_model` tag.
|
|
191
|
+
* Whenever the model resolves with usage, the span is also folded into the
|
|
192
|
+
* per-model `cost.by_model` rollup (tokens always; cost when priceable).
|
|
193
|
+
*
|
|
194
|
+
* The OpenInference-style `llm.*` duplicates (`llm.model_name` /
|
|
195
|
+
* `llm.model_provider` / `llm.usage.prompt_tokens_cost` /
|
|
196
|
+
* `llm.usage.completion_tokens_cost`) mirror the MLflow-convention attributes
|
|
197
|
+
* because the Databricks experiment Overview dashboard aggregates cost from
|
|
198
|
+
* those keys via `variant_get` on the UC span table — without them, Cost
|
|
199
|
+
* Breakdown / Cost Over Time render $0.00. The cost values must
|
|
200
|
+
* stay numbers: `variant_get(..., 'DOUBLE')` returns NULL for strings.
|
|
201
|
+
*/
|
|
202
|
+
private enrichLLMSpan;
|
|
203
|
+
/**
|
|
204
|
+
* Write token-usage span attributes. The reserved `mlflow.chat.tokenUsage`
|
|
205
|
+
* attribute carries MLflow's `TokenUsageKey` shape extended with the two cache
|
|
206
|
+
* slots — `{ input_tokens, output_tokens, total_tokens, cache_read_input_tokens,
|
|
207
|
+
* cache_creation_input_tokens }` — so they survive Databricks ingestion and
|
|
208
|
+
* render in the UI usage breakdown. The non-reserved `gen_ai.usage.*`
|
|
209
|
+
* token-count attrs mirror the Python `_write_token_usage`.
|
|
210
|
+
*/
|
|
211
|
+
private writeTokenUsage;
|
|
212
|
+
/**
|
|
213
|
+
* Write the trace-level cost rollups + `cost.unknown_model` tag (Python
|
|
214
|
+
* `_write_root_trace_rollup`). `mlflow.trace.cost` is the reserved MLflow
|
|
215
|
+
* `CostKey` shape — exactly `{ input_cost, output_cost, total_cost }`;
|
|
216
|
+
* Databricks strips any extra key on ingestion. `total_cost` already accounts
|
|
217
|
+
* for the cached discount and cache-creation premium; the per-line-item split
|
|
218
|
+
* lives on the spans.
|
|
219
|
+
*
|
|
220
|
+
* `cost.by_model` is the non-reserved per-model breakdown: emitted
|
|
221
|
+
* as a JSON string under a **trace tag** (like `cost.unknown_model`) rather
|
|
222
|
+
* than a custom metadata key — tags are proven to survive Databricks UC
|
|
223
|
+
* ingestion and stay queryable from the `*_trace_unified` view. Each bucket
|
|
224
|
+
* carries cost and tokens; the per-model totals reconcile with
|
|
225
|
+
* `mlflow.trace.cost` / `mlflow.chat.tokenUsage` within rounding. Models are
|
|
226
|
+
* emitted in sorted order, mirroring the Python tracer (the JSON parses to the
|
|
227
|
+
* same structure; the serialized bytes differ — Python `json.dumps` inserts
|
|
228
|
+
* `", "` / `": "` separators and renders integral zero floats as `0.0`).
|
|
229
|
+
*
|
|
230
|
+
* Must run before the root `span.end()` (see {@link onRunUpdate}).
|
|
231
|
+
*/
|
|
232
|
+
private writeRootTraceRollup;
|
|
233
|
+
protected persistRun(_run: Run): Promise<void>;
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=databricks-tracer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databricks-tracer.d.ts","sourceRoot":"","sources":["../src/databricks-tracer.ts"],"names":[],"mappings":"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"}
|