Skip to content

Commit 421bf28

Browse files
authored
fix(llamaindex): report inputs/outputs (#132)
1 parent 85725dc commit 421bf28

File tree

4 files changed

+97
-24
lines changed

4 files changed

+97
-24
lines changed

packages/instrumentation-llamaindex/recordings/Test-LlamaIndex-instrumentation_1988279490/should-add-span-for-all-instrumented-methods_2883459899/recording.har

Lines changed: 19 additions & 19 deletions
Large diffs are not rendered by default.

packages/instrumentation-llamaindex/src/instrumentation.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323

2424
import { LlamaIndexInstrumentationConfig } from "./types";
2525
import { CustomLLMInstrumentation } from "./custom-llm-instrumentation";
26-
import { genericWrapper } from "./utils";
26+
import { genericWrapper, shouldSendPrompts } from "./utils";
2727

2828
import { BaseEmbedding, BaseSynthesizer, LLM, BaseRetriever } from "llamaindex";
2929
import { TraceloopSpanKindValues } from "@traceloop/ai-semantic-conventions";
@@ -102,6 +102,7 @@ export class LlamaIndexInstrumentation extends InstrumentationBase<any> {
102102
"query",
103103
TraceloopSpanKindValues.WORKFLOW,
104104
this.tracer,
105+
shouldSendPrompts(this._config),
105106
),
106107
);
107108

@@ -113,6 +114,7 @@ export class LlamaIndexInstrumentation extends InstrumentationBase<any> {
113114
"chat",
114115
TraceloopSpanKindValues.WORKFLOW,
115116
this.tracer,
117+
shouldSendPrompts(this._config),
116118
),
117119
);
118120

@@ -133,6 +135,7 @@ export class LlamaIndexInstrumentation extends InstrumentationBase<any> {
133135
"getQueryEmbedding",
134136
TraceloopSpanKindValues.TASK,
135137
this.tracer,
138+
shouldSendPrompts(this._config),
136139
),
137140
);
138141
} else if (this.isSynthesizer(cls.prototype)) {
@@ -144,6 +147,7 @@ export class LlamaIndexInstrumentation extends InstrumentationBase<any> {
144147
"synthesize",
145148
TraceloopSpanKindValues.TASK,
146149
this.tracer,
150+
shouldSendPrompts(this._config),
147151
),
148152
);
149153
} else if (this.isRetriever(cls.prototype)) {
@@ -155,6 +159,7 @@ export class LlamaIndexInstrumentation extends InstrumentationBase<any> {
155159
"retrieve",
156160
TraceloopSpanKindValues.TASK,
157161
this.tracer,
162+
shouldSendPrompts(this._config),
158163
),
159164
);
160165
}

packages/instrumentation-llamaindex/src/utils.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const shouldSendPrompts = (config: LlamaIndexInstrumentationConfig) => {
1515
.getValue(CONTEXT_KEY_ALLOW_TRACE_CONTENT);
1616

1717
if (contextShouldSendPrompts !== undefined) {
18-
return contextShouldSendPrompts;
18+
return !!contextShouldSendPrompts;
1919
}
2020

2121
return config.traceContent !== undefined ? config.traceContent : true;
@@ -45,6 +45,7 @@ export function genericWrapper(
4545
methodName: string,
4646
kind: TraceloopSpanKindValues,
4747
tracer: Tracer,
48+
shouldSendPrompts: boolean,
4849
) {
4950
// eslint-disable-next-line @typescript-eslint/ban-types
5051
return (original: Function) => {
@@ -57,6 +58,33 @@ export function genericWrapper(
5758
span.setAttribute(SpanAttributes.TRACELOOP_WORKFLOW_NAME, name);
5859
}
5960

61+
if (shouldSendPrompts) {
62+
try {
63+
if (
64+
args.length === 1 &&
65+
typeof args[0] === "object" &&
66+
!(args[0] instanceof Map)
67+
) {
68+
span.setAttribute(
69+
SpanAttributes.TRACELOOP_ENTITY_INPUT,
70+
JSON.stringify({ args: [], kwargs: args[0] }),
71+
);
72+
} else {
73+
span.setAttribute(
74+
SpanAttributes.TRACELOOP_ENTITY_INPUT,
75+
JSON.stringify({
76+
args: args.map((arg) =>
77+
arg instanceof Map ? Array.from(arg.entries()) : arg,
78+
),
79+
kwargs: {},
80+
}),
81+
);
82+
}
83+
} catch {
84+
/* empty */
85+
}
86+
}
87+
6088
const execContext = trace.setSpan(context.active(), span);
6189
const execPromise = safeExecuteInTheMiddle(
6290
() => {
@@ -71,8 +99,25 @@ export function genericWrapper(
7199
.then((result: any) => {
72100
return new Promise((resolve) => {
73101
span.setStatus({ code: SpanStatusCode.OK });
74-
span.end();
75-
resolve(result);
102+
103+
try {
104+
if (shouldSendPrompts) {
105+
if (result instanceof Map) {
106+
span.setAttribute(
107+
SpanAttributes.TRACELOOP_ENTITY_OUTPUT,
108+
JSON.stringify(Array.from(result.entries())),
109+
);
110+
} else {
111+
span.setAttribute(
112+
SpanAttributes.TRACELOOP_ENTITY_OUTPUT,
113+
JSON.stringify(result),
114+
);
115+
}
116+
}
117+
} finally {
118+
span.end();
119+
resolve(result);
120+
}
76121
});
77122
})
78123
.catch((error: Error) => {

packages/instrumentation-llamaindex/test/instrumentation.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,33 @@ describe("Test LlamaIndex instrumentation", async function () {
171171
// TODO: Need to figure out why this doesn't get logged
172172
// assert.ok(spanNames.includes("get_query_embedding.task"));
173173

174-
assert.ok(spanNames.includes("retriever_query_engine.query"));
174+
const retrieverQueryEngineSpan = spans.find(
175+
(span) => span.name === "retriever_query_engine.query",
176+
);
177+
175178
assert.ok(spanNames.includes("retriever_query_engine.retrieve"));
176179
assert.ok(spanNames.includes("llamaindex.open_ai.chat"));
177180
assert.ok(spanNames.includes("response_synthesizer.synthesize"));
178181
assert.ok(spanNames.includes("vector_index_retriever.retrieve"));
182+
183+
assert.ok(retrieverQueryEngineSpan);
184+
assert.ok(retrieverQueryEngineSpan.attributes["traceloop.entity.input"]);
185+
assert.ok(retrieverQueryEngineSpan.attributes["traceloop.entity.output"]);
186+
assert.strictEqual(
187+
JSON.parse(
188+
retrieverQueryEngineSpan.attributes[
189+
"traceloop.entity.input"
190+
].toString(),
191+
).kwargs.query,
192+
"Where was albert einstein born?",
193+
);
194+
assert.strictEqual(
195+
JSON.parse(
196+
retrieverQueryEngineSpan.attributes[
197+
"traceloop.entity.output"
198+
].toString(),
199+
).response,
200+
result.response,
201+
);
179202
}).timeout(60000);
180203
});

0 commit comments

Comments
 (0)