diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index 94624b9..1234e32 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -30,7 +30,7 @@ jobs: - name: Publish to Sonatype run: | - ./gradlew publish --stacktrace + ./gradlew publishToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" env: SONATYPE_USERNAME: ${{ secrets.LANG_SMITH_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} SONATYPE_PASSWORD: ${{ secrets.LANG_SMITH_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} diff --git a/.gradle/8.0.2/executionHistory/executionHistory.bin b/.gradle/8.0.2/executionHistory/executionHistory.bin index 64dae6b..836ab63 100644 Binary files a/.gradle/8.0.2/executionHistory/executionHistory.bin and b/.gradle/8.0.2/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.0.2/executionHistory/executionHistory.lock b/.gradle/8.0.2/executionHistory/executionHistory.lock index c65498c..2c17ba2 100644 Binary files a/.gradle/8.0.2/executionHistory/executionHistory.lock and b/.gradle/8.0.2/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.0.2/fileHashes/fileHashes.bin b/.gradle/8.0.2/fileHashes/fileHashes.bin index fbdc5f7..cafd793 100644 Binary files a/.gradle/8.0.2/fileHashes/fileHashes.bin and b/.gradle/8.0.2/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.0.2/fileHashes/fileHashes.lock b/.gradle/8.0.2/fileHashes/fileHashes.lock index 086703b..f268446 100644 Binary files a/.gradle/8.0.2/fileHashes/fileHashes.lock and b/.gradle/8.0.2/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.0.2/fileHashes/resourceHashesCache.bin b/.gradle/8.0.2/fileHashes/resourceHashesCache.bin index 3fc94f4..37ff1a1 100644 Binary files a/.gradle/8.0.2/fileHashes/resourceHashesCache.bin and b/.gradle/8.0.2/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index dcca89d..0aa5c46 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin index 9905ebd..f82c777 100644 Binary files a/.gradle/buildOutputCleanup/outputFiles.bin and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ba6c348..f14b480 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.1" + ".": "0.1.0-alpha.2" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af2c4d..a03a221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.1.0-alpha.2 (2024-03-22) + +Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/langchain-ai/langsmith-java/compare/v0.1.0-alpha.1...v0.1.0-alpha.2) + +### Features + +* do not inline example ([fa22fd7](https://github.com/langchain-ai/langsmith-java/commit/fa22fd702baaaaa6c1062c73571360210a63de5c)) +* fix link ([c6b8b73](https://github.com/langchain-ai/langsmith-java/commit/c6b8b737b6214b717f747002f4f5f314ebce7fbb)) +* update builder patterns, use end options ([33019db](https://github.com/langchain-ai/langsmith-java/commit/33019db58bbbb63590dacbecd60548ea3f76ebd3)) +* update README ([aa6b46d](https://github.com/langchain-ai/langsmith-java/commit/aa6b46d44f8f7b15d342d7bb4defc566fd6f5369)) +* updates ([eb0044a](https://github.com/langchain-ai/langsmith-java/commit/eb0044a2a4b0d7f90e9842eb7fa53503d7c85232)) +* Use new sonatype publishing plugin ([d3f8fb2](https://github.com/langchain-ai/langsmith-java/commit/d3f8fb2c0931c78f9a830b3fd4d0a398e5c481f1)) + ## 0.1.0-alpha.1 (2024-03-19) Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/langchain-ai/langsmith-java/compare/v0.0.1-alpha.0...v0.1.0-alpha.1) diff --git a/README.md b/README.md index 3d899b3..1247bc9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # Lang Smith Java API Library - - -[![Maven Central](https://img.shields.io/maven-central/v/com.langsmith.api/langsmith-java)](https://central.sonatype.com/artifact/com.langsmith.api/langsmith-java/0.1.0-alpha.1) - - +[![Maven Central](https://img.shields.io/maven-central/v/com.langsmith.api/langsmith-java)](https://central.sonatype.com/artifact/com.langsmith.api/langsmith-java/0.0.1-alpha.0) The Lang Smith Java SDK provides convenient access to the Lang Smith REST API from applications written in Java. It includes helper classes with helpful types and documentation for every request and response property. @@ -12,7 +8,7 @@ The Lang Smith Java SDK is similar to the Lang Smith Kotlin SDK but with minor d ## Documentation -The REST API documentation can be found [on docs.langsmith.com](https://docs.LangSmith.com). +The REST API documentation can be found [on docs.langsmith.com](https://api.smith.langchain.com/redoc). --- @@ -22,10 +18,8 @@ The REST API documentation can be found [on docs.langsmith.com](https://docs.La #### Gradle - - ```kotlin -implementation("com.langsmith.api:langsmith-java:0.1.0-alpha.1") +implementation("com.langsmith.api:langsmith-java:0.0.1-alpha.0") ``` #### Maven @@ -34,12 +28,10 @@ implementation("com.langsmith.api:langsmith-java:0.1.0-alpha.1") com.langsmith.api langsmith-java - 0.1.0-alpha.1 + 0.0.1-alpha.0 ``` - - ### Configure the client Use `LangSmithOkHttpClient.builder()` to configure the client. At a minimum you need to set `.apiKey()`: @@ -71,8 +63,20 @@ LangSmithClient client = LangSmithOkHttpClient.builder() Read the documentation for more configuration options. +You can also set the `LANGCHAIN_PROJECT` to post runs to a specific project. +If unspecified, runs will be posted to the `default` project. + +| Property | Environment variable | Required | Default value | +| -------- | -------------------- | -------- | ------------- | +| project | `LANGCHAIN_PROJECT` | false | — | + --- +### Example: using the RunTree API (experimental) +The RunTree API is currently the recommended way to post runs to LangSmith. + +See a full example in the [here](./examples/src/main/java/com/langsmith/example/OpenAiExample.java). + ### Example: creating a resource To create a new run, first use the `RunBatchParams` builder to specify attributes, @@ -157,22 +161,22 @@ This library throws exceptions in a single hierarchy for easy handling: - **`LangSmithException`** - Base exception for all exceptions - - **`LangSmithServiceException`** - HTTP errors with a well-formed response body we were able to parse. The exception message and the `.debuggingRequestId()` will be set by the server. - - | 400 | BadRequestException | - | ------ | ----------------------------- | - | 401 | AuthenticationException | - | 403 | PermissionDeniedException | - | 404 | NotFoundException | - | 422 | UnprocessableEntityException | - | 429 | RateLimitException | - | 5xx | InternalServerException | - | others | UnexpectedStatusCodeException | - - - **`LangSmithIoException`** - I/O networking errors - - **`LangSmithInvalidDataException`** - any other exceptions on the client side, e.g.: - - We failed to serialize the request body - - We failed to parse the response body (has access to response code and body) + - **`LangSmithServiceException`** - HTTP errors with a well-formed response body we were able to parse. The exception message and the `.debuggingRequestId()` will be set by the server. + + | 400 | BadRequestException | + | ------ | ----------------------------- | + | 401 | AuthenticationException | + | 403 | PermissionDeniedException | + | 404 | NotFoundException | + | 422 | UnprocessableEntityException | + | 429 | RateLimitException | + | 5xx | InternalServerException | + | others | UnexpectedStatusCodeException | + + - **`LangSmithIoException`** - I/O networking errors + - **`LangSmithInvalidDataException`** - any other exceptions on the client side, e.g.: + - We failed to serialize the request body + - We failed to parse the response body (has access to response code and body) ## Network options diff --git a/build.gradle.kts b/build.gradle.kts index 2de7a88..16e1db8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,20 +1,6 @@ -plugins { - id("io.github.gradle-nexus.publish-plugin") version "1.1.0" -} allprojects { group = "com.langsmith.api" - version = "0.1.0-alpha.1" // x-release-please-version + version = "0.1.0-alpha.2" // x-release-please-version } -nexusPublishing { - repositories { - sonatype { - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - - username.set(System.getenv("SONATYPE_USERNAME")) - password.set(System.getenv("SONATYPE_PASSWORD")) - } - } -} diff --git a/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.bin b/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.bin index 9ec14a3..7af6511 100644 Binary files a/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.bin and b/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.bin differ diff --git a/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.lock b/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.lock index 820e438..2548a5c 100644 Binary files a/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.lock and b/buildSrc/.gradle/8.0.2/executionHistory/executionHistory.lock differ diff --git a/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 845e823..d1f1cd6 100644 Binary files a/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin b/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin index 7e237e6..cb7dd8d 100644 Binary files a/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin and b/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index aed1bd2..ce3b9a7 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,12 +1,16 @@ plugins { `kotlin-dsl` + kotlin("jvm") version "1.9.22" + id("com.vanniktech.maven.publish") version "0.28.0" } repositories { gradlePluginPortal() + mavenCentral() } dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.25.0") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22") + implementation("com.vanniktech:gradle-maven-publish-plugin:0.28.0") } diff --git a/buildSrc/src/main/kotlin/langsmith.java.gradle.kts b/buildSrc/src/main/kotlin/langsmith.java.gradle.kts index 0a33327..641f420 100644 --- a/buildSrc/src/main/kotlin/langsmith.java.gradle.kts +++ b/buildSrc/src/main/kotlin/langsmith.java.gradle.kts @@ -1,6 +1,9 @@ import com.diffplug.gradle.spotless.SpotlessExtension +import com.vanniktech.maven.publish.JavaLibrary +import com.vanniktech.maven.publish.JavadocJar +import com.vanniktech.maven.publish.MavenPublishBaseExtension +import com.vanniktech.maven.publish.SonatypeHost import org.gradle.api.tasks.testing.logging.TestExceptionFormat -import java.util.Locale plugins { `java-library` @@ -11,11 +14,6 @@ repositories { mavenCentral() } -configure { - withJavadocJar() - withSourcesJar() -} - configure { java { importOrder() @@ -35,10 +33,6 @@ tasks.withType { options.release.set(8) } -tasks.named("javadocJar") { - setZip64(true) -} - tasks.jar { manifest { attributes(mapOf( diff --git a/buildSrc/src/main/kotlin/langsmith.kotlin.gradle.kts b/buildSrc/src/main/kotlin/langsmith.kotlin.gradle.kts index 83b0893..9e42df7 100644 --- a/buildSrc/src/main/kotlin/langsmith.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/langsmith.kotlin.gradle.kts @@ -1,4 +1,5 @@ import com.diffplug.gradle.spotless.SpotlessExtension +import com.vanniktech.maven.publish.* import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/buildSrc/src/main/kotlin/langsmith.publish.gradle.kts b/buildSrc/src/main/kotlin/langsmith.publish.gradle.kts index 4663b00..8f9a0a9 100644 --- a/buildSrc/src/main/kotlin/langsmith.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/langsmith.publish.gradle.kts @@ -1,3 +1,5 @@ +import com.vanniktech.maven.publish.MavenPublishBaseExtension +import com.vanniktech.maven.publish.SonatypeHost import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.kotlin.dsl.configure @@ -5,63 +7,46 @@ import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.get plugins { - `maven-publish` - `signing` + id("com.vanniktech.maven.publish") } -configure { - publications { - create("maven") { - from(components["java"]) +repositories { + gradlePluginPortal() + mavenCentral() +} - pom { - name.set("LangSmith") - description.set("An SDK library for LangSmith") - url.set("https://docs.LangSmith.com") +extra["signingInMemoryKey"] = System.getenv("GPG_SIGNING_KEY") +extra["signingInMemoryKeyId"] = System.getenv("GPG_SIGNING_KEY_ID") +extra["signingInMemoryKeyPassword"] = System.getenv("GPG_SIGNING_PASSWORD") - licenses { - license { - name.set("Apache-2.0") - } - } +configure { + signAllPublications() + publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) - developers { - developer { - name.set("Lang Smith") - email.set("dev-feedback@LangSmith.com") - } - } + this.coordinates(project.group.toString(), project.name, project.version.toString()) - scm { - connection.set("scm:git:git://github.com/langchain-ai/langsmith-java.git") - developerConnection.set("scm:git:git://github.com/langchain-ai/langsmith-java.git") - url.set("https://github.com/langchain-ai/langsmith-java") - } + pom { + name.set("LangSmith") + description.set("An SDK library for LangSmith") + url.set("https://docs.LangSmith.com") - versionMapping { - allVariants { - fromResolutionResult() - } - } + licenses { + license { + name.set("Apache-2.0") } } - } -} -signing { - val signingKeyId = System.getenv("GPG_SIGNING_KEY_ID")?.ifBlank { null } - val signingKey = System.getenv("GPG_SIGNING_KEY")?.ifBlank { null } - val signingPassword = System.getenv("GPG_SIGNING_PASSWORD")?.ifBlank { null } - if (signingKey != null && signingPassword != null) { - useInMemoryPgpKeys( - signingKeyId, - signingKey, - signingPassword, - ) - sign(publishing.publications["maven"]) - } -} + developers { + developer { + name.set("Lang Smith") + email.set("dev-feedback@LangSmith.com") + } + } -tasks.publish { - dependsOn(":closeAndReleaseSonatypeStagingRepository") -} + scm { + connection.set("scm:git:git://github.com/langchain-ai/langsmith-java.git") + developerConnection.set("scm:git:git://github.com/langchain-ai/langsmith-java.git") + url.set("https://github.com/langchain-ai/langsmith-java") + } + } +} \ No newline at end of file diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3db8d72..d5c92f2 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -32,7 +32,7 @@ tasks.withType { } // Dynamically create a task for each example -val examples = listOf("RunTreeExample", "OpenAiExample") // Add the names of your example classes here +val examples = listOf("OpenAiExample") // Add the names of your example classes here examples.forEach { example -> tasks.create("run$example", org.gradle.api.tasks.JavaExec::class.java) { diff --git a/examples/src/main/java/com/langsmith/example/OpenAiExample.java b/examples/src/main/java/com/langsmith/example/OpenAiExample.java index fdd5c6b..9d68d6d 100644 --- a/examples/src/main/java/com/langsmith/example/OpenAiExample.java +++ b/examples/src/main/java/com/langsmith/example/OpenAiExample.java @@ -1,9 +1,11 @@ package com.langsmith.example; +import com.langsmith.runtree.EndOptions; import com.langsmith.runtree.RunTree; -import com.langsmith.runtree.RunTreeConfigBuilder; +import com.langsmith.runtree.RunTreeConfig; import com.theokanning.openai.service.OpenAiService; import com.theokanning.openai.completion.chat.*; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -16,12 +18,14 @@ public static void main(String[] args) { String question = "Can you summarize this morning's meetings?"; // Create a top-level run - RunTreeConfigBuilder pipelineConfigBuilder = new RunTreeConfigBuilder() + RunTreeConfig pipelineConfig = RunTreeConfig + .builder() .setName("Chat Pipeline") .setRunType("chain") - .setInputs(Collections.singletonMap("question", question)); + .setInputs(Collections.singletonMap("question", question)) + .build(); - RunTree pipeline = new RunTree(pipelineConfigBuilder.build()); + RunTree pipeline = new RunTree(pipelineConfig); var context = "During this morning's meeting, we solved all world conflict."; @@ -38,22 +42,30 @@ public static void main(String[] args) { .build(); // Create a child run - RunTreeConfigBuilder childConfigBuilder = new RunTreeConfigBuilder() + RunTreeConfig childConfig = RunTreeConfig + .builder() .setName("OpenAI Call") .setRunType("llm") .setInputs(Collections.singletonMap("messages", messages)) - .setParentRun(pipeline); + .setParentRun(pipeline) + .build(); - RunTree childTree = pipeline.createChild(childConfigBuilder.build()); + RunTree childTree = pipeline.createChild(childConfig); ChatMessage responseMessage = service.createChatCompletion(completionRequest).getChoices().get(0).getMessage(); System.out.println("Response: " + responseMessage.getContent()); // End the child run - childTree.end(Collections.singletonMap("response", responseMessage), null, null); + childTree.end(EndOptions + .builder() + .setOutputs(Collections.singletonMap("response", responseMessage)) + .build()); // End the parent run - pipeline.end(Collections.singletonMap("response", responseMessage.getContent()), null, null); + pipeline.end(EndOptions + .builder() + .setOutputs(Collections.singletonMap("response", responseMessage.getContent())) + .build()); childTree.postRunAsync().join(); pipeline.postRunAsync().join(); } diff --git a/examples/src/main/java/com/langsmith/example/RunTreeExample.java b/examples/src/main/java/com/langsmith/example/RunTreeExample.java deleted file mode 100644 index 52dfe12..0000000 --- a/examples/src/main/java/com/langsmith/example/RunTreeExample.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.langsmith.example; - -import com.langsmith.api.client.LangSmithClientAsync; -import com.langsmith.api.client.okhttp.LangSmithOkHttpClientAsync; -import com.langsmith.runtree.RunTree; -import com.langsmith.runtree.RunTreeConfigBuilder; - -import java.util.Map; - -public class RunTreeExample { - public static void main(String[] args) { - System.out.println("Hello, World!"); - - LangSmithClientAsync client = LangSmithOkHttpClientAsync.fromEnv(); - - // Create a RunTreeConfig object - var builder = new RunTreeConfigBuilder(); - builder.setName("Test Run"); - builder.setRunType("llm"); - builder.setInputs(Map.of("input", "Testing!")); - var config = builder.build(); - - // Create a RunTree object - RunTree runTree = new RunTree(config); - - var childBuilder = new RunTreeConfigBuilder(); - childBuilder.setName("Test Child Run"); - childBuilder.setInputs(Map.of("input", "Test2!")); - var childConfig = childBuilder.build(); - - // Time it - var startTime = System.currentTimeMillis(); - - // Using TLS - RunTree childTree = RunTree.fromCurrentSpan(childConfig); - var parentFuture = runTree.postRunAsync(); - parentFuture.join(); -// var endTime = System.currentTimeMillis(); -// var elapsedTime = endTime - startTime; -// System.out.println("Post1 elapsed time: " + elapsedTime + " milliseconds"); -// var childFuture = childTree.postRunAsync(); -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// System.out.println("Post2 time: " + elapsedTime + " milliseconds"); -// var childEndFuture = childTree.endAsync(Map.of("output", "Test Output"), null, null); -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// var endTime = System.currentTimeMillis(); -// var elapsedTime = endTime - startTime; -// System.out.println("Post1 elapsed time: " + elapsedTime + " milliseconds"); -// var childFuture = childTree.postRunAsync(true); -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// System.out.println("Post2 time: " + elapsedTime + " milliseconds"); -// var childEndFuture = childTree.endAsync(Map.of("output", "Test Output"), null, null); -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// System.out.println("End1 elapsed time: " + elapsedTime + " milliseconds"); -// var parentEndFuture = runTree.endAsync(Map.of("output", "Test Output Parent"), null, null); -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// System.out.println("End parent elapsed time: " + elapsedTime + " milliseconds"); -// -// // Calculate elapsed time -// endTime = System.currentTimeMillis(); -// elapsedTime = endTime - startTime; -// System.out.println("Total lapsed time: " + elapsedTime + " milliseconds"); - } -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1bef7e..fae0804 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/langsmith-java-trace/src/main/kotlin/com/langsmith/runtree/RunTree.kt b/langsmith-java-trace/src/main/kotlin/com/langsmith/runtree/RunTree.kt index 418249a..aa5c939 100644 --- a/langsmith-java-trace/src/main/kotlin/com/langsmith/runtree/RunTree.kt +++ b/langsmith-java-trace/src/main/kotlin/com/langsmith/runtree/RunTree.kt @@ -70,6 +70,30 @@ fun getTracerProject(): String { ?: "default" } +data class EndOptions( + val outputs: Map? = null, + val errorMessage: String? = null, + val endTime: Long? = null +) { + companion object { + @JvmStatic fun builder() = Builder() + } + + class Builder { + private var outputs: Map? = null + private var errorMessage: String? = null + private var endTime: Long? = null + + fun setOutputs(value: Map?) = apply { outputs = value } + + fun setErrorMessage(value: String?) = apply { errorMessage = value } + + fun setEndTime(value: Long?) = apply { endTime = value } + + fun build(): EndOptions = EndOptions(outputs, errorMessage, endTime) + } +} + data class RunTreeConfig( val name: String, val runType: String = "chain", @@ -89,87 +113,91 @@ data class RunTreeConfig( val referenceExampleId: String? = null, val client: LangSmithClientAsync = LangSmithOkHttpClientAsync.fromEnv(), val objectMapper: ObjectMapper = jacksonObjectMapper() -) +) { + companion object { + @JvmStatic fun builder() = Builder() + } -class RunTreeConfigBuilder { - private var name: String = "" - private var runType: String = "chain" - private var id: String = UUID.randomUUID().toString() - private var projectName: String = getTracerProject() - private var parentRun: RunTree? = null - private var parentRunId: String? = null - private var childRuns: MutableList = mutableListOf() - private var startTime: Long = System.currentTimeMillis() - private var endTime: Long? = null - private var extra: Map = emptyMap() - private var tags: List = ArrayList() - private var error: String? = null - private var serialized: Map = emptyMap() - private var inputs: Map = emptyMap() - private var outputs: Map? = emptyMap() - private var referenceExampleId: String? = null - private var client: LangSmithClientAsync? = null - private var objectMapper: ObjectMapper = jacksonObjectMapper() + class Builder { + private var name: String = "" + private var runType: String = "chain" + private var id: String = UUID.randomUUID().toString() + private var projectName: String = getTracerProject() + private var parentRun: RunTree? = null + private var parentRunId: String? = null + private var childRuns: MutableList = mutableListOf() + private var startTime: Long = System.currentTimeMillis() + private var endTime: Long? = null + private var extra: Map = emptyMap() + private var tags: List = ArrayList() + private var error: String? = null + private var serialized: Map = emptyMap() + private var inputs: Map = emptyMap() + private var outputs: Map? = emptyMap() + private var referenceExampleId: String? = null + private var client: LangSmithClientAsync? = null + private var objectMapper: ObjectMapper = jacksonObjectMapper() - fun setName(value: String) = apply { name = value } + fun setName(value: String) = apply { name = value } - fun setRunType(value: String) = apply { runType = value } + fun setRunType(value: String) = apply { runType = value } - fun setId(value: String) = apply { id = value } + fun setId(value: String) = apply { id = value } - fun setProjectName(value: String) = apply { projectName = value } + fun setProjectName(value: String) = apply { projectName = value } - fun setParentRun(value: RunTree?) = apply { parentRun = value } + fun setParentRun(value: RunTree?) = apply { parentRun = value } - fun setParentRunId(value: String?) = apply { parentRunId = value } + fun setParentRunId(value: String?) = apply { parentRunId = value } - fun addChildRun(value: RunTree) = apply { childRuns.add(value) } + fun addChildRun(value: RunTree) = apply { childRuns.add(value) } - fun setStartTime(value: Long) = apply { startTime = value } + fun setStartTime(value: Long) = apply { startTime = value } - fun setEndTime(value: Long?) = apply { endTime = value } + fun setEndTime(value: Long?) = apply { endTime = value } - fun setExtra(value: Map) = apply { extra = value } + fun setExtra(value: Map) = apply { extra = value } - fun setTags(value: List) = apply { tags = value } + fun setTags(value: List) = apply { tags = value } - fun setError(value: String?) = apply { error = value } + fun setError(value: String?) = apply { error = value } - fun setSerialized(value: Map) = apply { serialized = value } + fun setSerialized(value: Map) = apply { serialized = value } - fun setInputs(value: Map) = apply { inputs = value } + fun setInputs(value: Map) = apply { inputs = value } - fun setOutputs(value: Map?) = apply { outputs = value } + fun setOutputs(value: Map?) = apply { outputs = value } - fun setReferenceExampleId(value: String?) = apply { referenceExampleId = value } + fun setReferenceExampleId(value: String?) = apply { referenceExampleId = value } - fun setClient(value: LangSmithClientAsync?) = apply { client = value } + fun setClient(value: LangSmithClientAsync?) = apply { client = value } - fun setObjectMapper(value: ObjectMapper) = apply { objectMapper = value } + fun setObjectMapper(value: ObjectMapper) = apply { objectMapper = value } - fun addExtra(key: String, value: Any) = apply { extra = extra.plus(key to value) } + fun addExtra(key: String, value: Any) = apply { extra = extra.plus(key to value) } - fun build(): RunTreeConfig = - RunTreeConfig( - name = name, - runType = runType, - id = id, - projectName = projectName, - parentRun = parentRun, - parentRunId = parentRunId, - childRuns = childRuns, - startTime = startTime, - endTime = endTime, - extra = extra, - tags = tags, - error = error, - serialized = serialized, - inputs = inputs, - outputs = outputs, - referenceExampleId = referenceExampleId, - client = client ?: LangSmithOkHttpClientAsync.fromEnv(), - objectMapper = objectMapper - ) + fun build(): RunTreeConfig = + RunTreeConfig( + name = name, + runType = runType, + id = id, + projectName = projectName, + parentRun = parentRun, + parentRunId = parentRunId, + childRuns = childRuns, + startTime = startTime, + endTime = endTime, + extra = extra, + tags = tags, + error = error, + serialized = serialized, + inputs = inputs, + outputs = outputs, + referenceExampleId = referenceExampleId, + client = client ?: LangSmithOkHttpClientAsync.fromEnv(), + objectMapper = objectMapper + ) + } } class RunTree(config: RunTreeConfig) { @@ -284,9 +312,9 @@ class RunTree(config: RunTreeConfig) { return client.runs().update(updateParams).thenApply { _ -> Unit } } - fun end(outputs: Map? = null, error: String? = null, endTime: Long? = null) { - this.outputs = outputs - this.error = error - this.endTime = endTime ?: System.currentTimeMillis() + fun end(options: EndOptions = EndOptions()) { + this.outputs = options.outputs + this.error = options.errorMessage + this.endTime = options.endTime ?: System.currentTimeMillis() } } diff --git a/langsmith-java-trace/src/main/kotlin/com/langsmith/traceable/Traceable.kt b/langsmith-java-trace/src/main/kotlin/com/langsmith/traceable/Traceable.kt index 490eac1..283f8bf 100644 --- a/langsmith-java-trace/src/main/kotlin/com/langsmith/traceable/Traceable.kt +++ b/langsmith-java-trace/src/main/kotlin/com/langsmith/traceable/Traceable.kt @@ -1,8 +1,9 @@ package com.langsmith.traceable import com.fasterxml.jackson.databind.ObjectMapper +import com.langsmith.runtree.EndOptions import com.langsmith.runtree.RunTree -import com.langsmith.runtree.RunTreeConfigBuilder +import com.langsmith.runtree.RunTreeConfig import java.util.concurrent.CompletableFuture import java.util.function.Function @@ -71,7 +72,7 @@ class Traceable { ): R { val traceConfig = config ?: TraceConfig() val builder = - RunTreeConfigBuilder() + RunTreeConfig.builder() .setName(traceConfig.name ?: function::class.simpleName ?: "Anonymous") .setRunType(traceConfig.runType ?: "chain") .setTags(traceConfig.tags ?: emptyList()) @@ -95,11 +96,11 @@ class Traceable { try { val result = function.apply(traceableInput.input) - runTree.end(convertToMap(result), null, null) + runTree.end(EndOptions(outputs = convertToMap(result))) CompletableFuture.allOf(postFuture).join() return result } catch (e: Throwable) { - runTree.end(null, e.toString(), null) + runTree.end(EndOptions(errorMessage = e.toString())) CompletableFuture.allOf(postFuture).join() throw e }