Set Input/Output
Learn how to supply input and output of your LLM application in a trace
Overview
Both traces and spans have inputs and outputs, which you can set dynamically within your application using the update_current_span/updateCurrentSpan and update_current_trace/updateCurrentTrace function respectively.
Set Trace I/O
By default, the input and output of a trace is defaulted to the input arguments of the first span and the output of the last span you've wrapped/decorated. You can however override the input and output on spans at runtime.
from openai import OpenAI
from deepeval.tracing import observe, update_current_trace
client = OpenAI()
@observe()
def llm_app(query: str):
res = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
).choices[0].message.content
update_current_trace(input=query, output=res)
return res
llm_app("Write me a poem.")import OpenAI from 'openai';
import { observe, updateCurrentTrace } from 'deepeval/tracing';
const openai = new OpenAI();
const llmApp = async (query: string) => {
const res = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: query }],
});
updateCurrentTrace({ input: query, output: res.choices[0].message.content });
return res.choices[0].message.content;
};
const observedLlmApp = observe({ fn: llmApp });
observedLlmApp("Write me a poem.");The input and output can be ANY TYPE, and is useful for visualization on the UI (even more so if you're using conversation threads).
Set Span I/O
By default, the input and output of a span is defaulted to the input arguments and output of the function/method you're mapping. You can however override the input and output on spans at runtime.
from openai import OpenAI
from deepeval.tracing import observe, update_current_span
client = OpenAI()
@observe()
def llm_app(query: str):
res = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
).choices[0].message.content
update_current_span(input=query, output=res)
return res
llm_app("Write me a poem.")import OpenAI from 'openai';
import { observe, updateCurrentSpan } from 'deepeval/tracing';
const openai = new OpenAI();
const llmApp = async (query: string) => {
const res = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: query }],
});
updateCurrentSpan({ input: query, output: res.choices[0].message.content });
return res.choices[0].message.content;
};
const observedLlmApp = observe({ fn: llmApp });
observedLlmApp("Write me a poem.");This example is the same as the one for tracing except for the update_current_trace, and that's not a mistake. You can set input and outputs the same way as you do for traces, and if a trace's I/O is not set it defaults to the I/O of the root span.
The input and output can be ANY TYPE for custom span types, and is useful for visualization on the UI.
I/O for Streamed Responses
If your @observe-decorated function uses yield to stream its response, the trace output won't be captured automatically — the return value is a generator, not the final text. Collect the streamed chunks and set the output explicitly:
from deepeval.tracing import observe, update_current_trace
@observe()
def stream_response(query: str):
chunks = []
for chunk in llm.stream(query):
chunks.append(chunk)
yield chunk
update_current_trace(input=query, output="".join(chunks))import { observe, updateCurrentTrace } from "deepeval/tracing";
const streamResponse = async function* (query: string) {
const chunks: string[] = [];
for await (const chunk of llm.stream(query)) {
chunks.push(chunk);
yield chunk;
}
updateCurrentTrace({ input: query, output: chunks.join("") });
};
const observedStreamResponse = observe({ fn: streamResponse });Without this, the trace will appear on Confident AI with no output. See the troubleshooting page for more details.
I/O for Threads
For multu-turn AI apps that create a thread from the traces, it is highly recommended that you provide the strings instead, where the input will represent the user input, and output representing the AI generated output. You can also leave out any input or output for consecutive user/LLM behaviors.
You will also need the input and output to run online evaluations on a thread, as these will be used as the turns for a conversational test case.
Next Steps
With your trace and span I/O configured, connect traces into conversations or start evaluating them.
Thread Traces
Group traces into threads to track multi-turn conversations and evaluate entire workflows.
Online Evaluations
Run evaluations on traces, spans, and threads in real-time as they're ingested into Confident AI.
Last updated on