Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 0 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,65 +82,6 @@ var request =
var response = openAIClient.chat().completions().create(request);
```

### LangChain4j Instrumentation

```java
var braintrust = Braintrust.get();
var openTelemetry = braintrust.openTelemetryCreate();

// Wrap the chat model to trace LLM calls
ChatModel model = BraintrustLangchain.wrap(
openTelemetry,
OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.temperature(0.0));

var response = model.chat("What is the capital of France?");
```

#### Tool Wrapping

Use `BraintrustLangchain.wrapTools()` to automatically trace tool executions in your LangChain4j agents:

```java
// Create your tool class
public class WeatherTools {
@Tool("Get current weather for a location")
public String getWeather(String location) {
return "The weather in " + location + " is sunny.";
}
}

// Wrap tools to create spans for each tool execution
WeatherTools tools = new WeatherTools();
WeatherTools instrumentedTools = BraintrustLangchain.wrapTools(openTelemetry, tools);

// Use instrumented tools in your AI service
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(model)
.tools(instrumentedTools)
.build();
```

Each tool call will automatically create an OpenTelemetry span in Braintrust with:
- Tool name and parameters
- Execution duration
- Return values
- Any exceptions thrown

**Note:** For proper display in the Braintrust UI, ensure parent spans (conversation, turn, etc.) also set the required Braintrust attributes:
```java
var span = tracer.spanBuilder("my-span").startSpan();
span.setAttribute("braintrust.span_attributes", "{\"type\":\"task\",\"name\":\"my-span\"}");
span.setAttribute("braintrust.input_json", "{\"user_message\":\"...\"}");
// ... do work ...
span.setAttribute("braintrust.output_json", "{\"result\":\"...\"}");
span.end();
```

See [LangchainToolWrappingExample.java](./examples/src/main/java/dev/braintrust/examples/LangchainToolWrappingExample.java) for a complete example with proper span hierarchy.

## Running Examples

Example source code can be found [here](./examples/src/main/java/dev/braintrust/examples)
Expand Down
2 changes: 0 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ dependencies {
testImplementation "dev.langchain4j:langchain4j:${langchainVersion}"
testImplementation "dev.langchain4j:langchain4j-http-client:${langchainVersion}"
testImplementation "dev.langchain4j:langchain4j-open-ai:${langchainVersion}"

implementation 'net.bytebuddy:byte-buddy:1.14.11' // ByteBuddy for LangChain4j tool wrapping
}

/**
Expand Down
14 changes: 0 additions & 14 deletions examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,3 @@ task runLangchain(type: JavaExec) {
suspend = false
}
}

task runLangchainToolWrapping(type: JavaExec) {
group = 'Braintrust SDK Examples'
description = 'Run the LangChain4j tool wrapping example. NOTE: this requires OPENAI_API_KEY to be exported and will make a small call to openai, using your tokens'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'dev.braintrust.examples.LangchainToolWrappingExample'
systemProperty 'org.slf4j.simpleLogger.log.dev.braintrust', braintrustLogLevel
debugOptions {
enabled = true
port = 5566
server = true
suspend = false
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,6 @@ public static OpenAiStreamingChatModel wrap(
}
}

/**
* Wrap a tools object to instrument @Tool method executions with Braintrust traces. Returns a
* proxy that intercepts all @Tool annotated methods and creates OpenTelemetry spans.
*
* <p>Usage: StoryTools tools = new StoryTools(); StoryTools instrumented =
* BraintrustLangchain.wrapTools(openTelemetry, tools);
* AiServices.builder(Assistant.class).chatModel(model).tools(instrumented).build()
*
* @param otel OpenTelemetry instance from braintrust.openTelemetryCreate()
* @param tools Tool object with @Tool annotated methods
* @return Proxied tool object that creates spans for each @Tool method call
*/
@SuppressWarnings("unchecked")
public static <T> T wrapTools(OpenTelemetry otel, T tools) {
try {
return (T) new ByteBuddyToolWrapper(otel).wrap(tools);
} catch (Exception e) {
log.warn("Failed to wrap tools with instrumentation, returning original", e);
return tools;
}
}

private static HttpClientBuilder wrap(
OpenTelemetry otel, HttpClientBuilder builder, Options options) {
return new WrappedHttpClientBuilder(otel, builder, options);
Expand Down
Loading