import openai
import langsmith as ls
from langsmith.wrappers import wrap_openai
client = openai.Client()
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
# You can set metadata & tags **statically** when decorating a function
# Use the @traceable decorator with tags and metadata
# Ensure that the LANGSMITH_TRACING environment variables are set for @traceable to work
@ls.traceable(
run_type="llm",
name="OpenAI Call Decorator",
tags=["my-tag"],
metadata={"my-key": "my-value"}
)
def call_openai(
messages: list[dict], model: str = "gpt-4o-mini"
) -> str:
# You can also dynamically set metadata on the parent run:
rt = ls.get_current_run_tree()
rt.metadata["some-conditional-key"] = "some-val"
rt.tags.extend(["another-tag"])
return client.chat.completions.create(
model=model,
messages=messages,
).choices[0].message.content
call_openai(
messages,
# To add at **invocation time**, when calling the function.
# via the langsmith_extra parameter
langsmith_extra={"tags": ["my-other-tag"], "metadata": {"my-other-key": "my-value"}}
)
# Alternatively, you can use the context manager
with ls.trace(
name="OpenAI Call Trace",
run_type="llm",
inputs={"messages": messages},
tags=["my-tag"],
metadata={"my-key": "my-value"},
) as rt:
chat_completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
)
rt.metadata["some-conditional-key"] = "some-val"
rt.end(outputs={"output": chat_completion})
# You can use the same techniques with the wrapped client
patched_client = wrap_openai(
client, tracing_extra={"metadata": {"my-key": "my-value"}, "tags": ["a-tag"]}
)
chat_completion = patched_client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
langsmith_extra={
"tags": ["my-other-tag"],
"metadata": {"my-other-key": "my-value"},
},
)
import OpenAI from "openai";
import { traceable, getCurrentRunTree } from "langsmith/traceable";
import { wrapOpenAI } from "langsmith/wrappers";
const client = wrapOpenAI(new OpenAI());
const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Hello!" },
];
const traceableCallOpenAI = traceable(
async (messages: OpenAI.Chat.ChatCompletionMessageParam[]) => {
const completion = await client.chat.completions.create({
model: "gpt-4o-mini",
messages,
});
const runTree = getCurrentRunTree();
runTree.extra.metadata = {
...runTree.extra.metadata,
someKey: "someValue",
};
runTree.tags = [...(runTree.tags ?? []), "runtime-tag"];
return completion.choices[0].message.content;
},
{
run_type: "llm",
name: "OpenAI Call Traceable",
tags: ["my-tag"],
metadata: { "my-key": "my-value" },
}
);
// Call the traceable function
await traceableCallOpenAI(messages);
import com.langchain.smith.wrappers.openai.OpenTelemetryConfig;
import com.langchain.smith.wrappers.openai.WrappedOpenAIClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
public class MetadataTagsExample {
public static void main(String[] args) {
// Configure OpenTelemetry
OpenTelemetryConfig.builder()
.fromEnv()
.build();
// Get tracer
Tracer tracer = GlobalOpenTelemetry.get().getTracer("my-app");
WrappedOpenAIClient client = WrappedOpenAIClient.fromEnv();
// Create a span with metadata and tags
Span span = tracer.spanBuilder("openai_call")
.setAttribute("langsmith.span.kind", "llm")
// Add metadata as span attributes
.setAttribute("my-key", "my-value")
.setAttribute("environment", "production")
// Add tags as a comma-separated string
.setAttribute("langsmith.tags", "my-tag,another-tag")
.startSpan();
try (Scope scope = span.makeCurrent()) {
ChatCompletion completion = client.chat().completions().create(
ChatCompletionCreateParams.builder()
.model(ChatModel.GPT_4O_MINI)
.addSystemMessage("You are a helpful assistant.")
.addUserMessage("Hello!")
.build()
);
// Add dynamic metadata during execution
span.setAttribute("response-length",
completion.choices().get(0).message().content().orElse("").length());
span.setAttribute("user-id", "user-123");
System.out.println(completion.choices().get(0).message().content().orElse(""));
} finally {
span.end();
}
client.close();
OpenTelemetryConfig.flush(5, java.util.concurrent.TimeUnit.SECONDS);
}
}
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.