Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js feat: Support attachments in traceable #1169

Merged
merged 13 commits into from
Nov 6, 2024
23 changes: 15 additions & 8 deletions js/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as uuid from "uuid";

Check notice on line 1 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... create_5_000_run_trees: Mean +- std dev: 619 ms +- 45 ms ......................................... create_10_000_run_trees: Mean +- std dev: 1.21 sec +- 0.06 sec ......................................... create_20_000_run_trees: Mean +- std dev: 1.19 sec +- 0.05 sec ......................................... dumps_class_nested_py_branch_and_leaf_200x400: Mean +- std dev: 705 us +- 13 us ......................................... dumps_class_nested_py_leaf_50x100: Mean +- std dev: 24.9 ms +- 0.3 ms ......................................... dumps_class_nested_py_leaf_100x200: Mean +- std dev: 103 ms +- 3 ms ......................................... dumps_dataclass_nested_50x100: Mean +- std dev: 25.3 ms +- 0.6 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (14.5 ms) is 22% of the mean (64.5 ms) * the maximum (99.6 ms) is 54% greater than the mean (64.5 ms) Try to rerun the benchmark with more runs, values and/or loops. Run 'python -m pyperf system tune' command to reduce the system jitter. Use pyperf stats, pyperf dump and pyperf hist to analyze results. Use --quiet option to hide these warnings. dumps_pydantic_nested_50x100: Mean +- std dev: 64.5 ms +- 14.5 ms ......................................... WARNING: the benchmark result may be unstable * the standard deviation (29.1 ms) is 14% of the mean (215 ms) Try to rerun the benchmark with more runs, values and/or loops. Run 'python -m pyperf system tune' command to reduce the system jitter. Use pyperf stats, pyperf dump and pyperf hist to analyze results. Use --quiet option to hide these warnings. dumps_pydanticv1_nested_50x100: Mean +- std dev: 215 ms +- 29 ms

Check notice on line 1 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------------+----------+------------------------+ | Benchmark | main | changes | +===============================================+==========+========================+ | dumps_pydanticv1_nested_50x100 | 223 ms | 215 ms: 1.04x faster | +-----------------------------------------------+----------+------------------------+ | dumps_class_nested_py_leaf_50x100 | 25.6 ms | 24.9 ms: 1.03x faster | +-----------------------------------------------+----------+------------------------+ | dumps_class_nested_py_leaf_100x200 | 105 ms | 103 ms: 1.02x faster | +-----------------------------------------------+----------+------------------------+ | dumps_dataclass_nested_50x100 | 25.8 ms | 25.3 ms: 1.02x faster | +-----------------------------------------------+----------+------------------------+ | dumps_class_nested_py_branch_and_leaf_200x400 | 696 us | 705 us: 1.01x slower | +-----------------------------------------------+----------+------------------------+ | create_10_000_run_trees | 1.19 sec | 1.21 sec: 1.02x slower | +-----------------------------------------------+----------+------------------------+ | Geometric mean | (ref) | 1.01x faster | +-----------------------------------------------+----------+------------------------+ Benchmark hidden because not significant (3): dumps_pydantic_nested_50x100, create_5_000_run_trees, create_20_000_run_trees

import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js";
import {
Expand Down Expand Up @@ -34,6 +34,7 @@
ValueType,
AnnotationQueue,
RunWithAnnotationQueueInfo,
Attachments,
} from "./schemas.js";
import {
convertLangChainMessageToExample,
Expand Down Expand Up @@ -240,7 +241,7 @@
revision_id?: string;
trace_id?: string;
dotted_order?: string;
attachments?: Record<string, [string, Uint8Array]>;
attachments?: Attachments;
}

interface UpdateRunParams extends RunUpdate {
Expand Down Expand Up @@ -419,7 +420,7 @@
// If there is an item on the queue we were unable to pop,
// just return it as a single batch.
if (popped.length === 0 && this.items.length > 0) {
const item = this.items.shift()!;

Check warning on line 423 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Forbidden non-null assertion
popped.push(item);
poppedSizeBytes += item.size;
this.sizeBytes -= item.size;
Expand Down Expand Up @@ -843,7 +844,7 @@
if (this._serverInfo === undefined) {
try {
this._serverInfo = await this._getServerInfo();
} catch (e) {

Check warning on line 847 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

'e' is defined but never used. Allowed unused args must match /^_/u
console.warn(
`[WARNING]: LangSmith failed to fetch info on supported operations. Falling back to single calls and default limits.`
);
Expand Down Expand Up @@ -1032,10 +1033,7 @@
return;
}
// transform and convert to dicts
const allAttachments: Record<
string,
Record<string, [string, Uint8Array]>
> = {};
const allAttachments: Record<string, Attachments> = {};
let preparedCreateParams = [];
for (const create of runCreates ?? []) {
const preparedCreate = this.prepareRunCreateOrUpdateInputs(create);
Expand All @@ -1048,7 +1046,6 @@
delete preparedCreate.attachments;
preparedCreateParams.push(preparedCreate);
}

let preparedUpdateParams = [];
for (const update of runUpdates ?? []) {
preparedUpdateParams.push(this.prepareRunCreateOrUpdateInputs(update));
Expand Down Expand Up @@ -1116,7 +1113,8 @@
]) {
for (const originalPayload of payloads) {
// collect fields to be sent as separate parts
const { inputs, outputs, events, ...payload } = originalPayload;
const { inputs, outputs, events, attachments, ...payload } =
originalPayload;
const fields = { inputs, outputs, events };
// encode the main run payload
const stringifiedPayload = stringifyForTracing(payload);
Expand Down Expand Up @@ -1147,10 +1145,18 @@
for (const [name, [contentType, content]] of Object.entries(
attachments
)) {
// Validate that the attachment name doesn't contain a '.'
if (name.includes(".")) {
console.warn(
`Skipping attachment '${name}' for run ${payload.id}: Invalid attachment name. ` +
`Attachment names must not contain periods ('.'). Please rename the attachment and try again.`
);
continue;
}
accumulatedParts.push({
name: `attachment.${payload.id}.${name}`,
payload: new Blob([content], {
type: `${contentType}; length=${content.length}`,
type: `${contentType}; length=${content.byteLength}`,
}),
});
}
Expand All @@ -1172,6 +1178,7 @@
for (const part of parts) {
formData.append(part.name, part.payload);
}
// Log the form data
await this.batchIngestCaller.call(
_getFetchImplementation(),
`${this.apiUrl}/runs/multipart`,
Expand Down Expand Up @@ -1553,7 +1560,7 @@
treeFilter?: string;
isRoot?: boolean;
dataSourceType?: string;
}): Promise<any> {

Check warning on line 1563 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
let projectIds_ = projectIds || [];
if (projectNames) {
projectIds_ = [
Expand Down Expand Up @@ -1841,7 +1848,7 @@
`Failed to list shared examples: ${response.status} ${response.statusText}`
);
}
return result.map((example: any) => ({

Check warning on line 1851 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
...example,
_hostUrl: this.getHostUrl(),
}));
Expand Down Expand Up @@ -1978,7 +1985,7 @@
}
// projectId querying
return true;
} catch (e) {

Check warning on line 1988 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

'e' is defined but never used. Allowed unused args must match /^_/u
return false;
}
}
Expand Down Expand Up @@ -3318,7 +3325,7 @@
async _logEvaluationFeedback(
evaluatorResponse: EvaluationResult | EvaluationResults,
run?: Run,
sourceInfo?: { [key: string]: any }

Check warning on line 3328 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
): Promise<[results: EvaluationResult[], feedbacks: Feedback[]]> {
const evalResults: Array<EvaluationResult> =
this._selectEvalResults(evaluatorResponse);
Expand Down Expand Up @@ -3357,7 +3364,7 @@
public async logEvaluationFeedback(
evaluatorResponse: EvaluationResult | EvaluationResults,
run?: Run,
sourceInfo?: { [key: string]: any }

Check warning on line 3367 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
): Promise<EvaluationResult[]> {
const [results] = await this._logEvaluationFeedback(
evaluatorResponse,
Expand Down Expand Up @@ -3807,7 +3814,7 @@

public async createCommit(
promptIdentifier: string,
object: any,

Check warning on line 3817 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
options?: {
parentCommitHash?: string;
}
Expand Down Expand Up @@ -3858,7 +3865,7 @@
isPublic?: boolean;
isArchived?: boolean;
}
): Promise<Record<string, any>> {

Check warning on line 3868 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type
if (!(await this.promptExists(promptIdentifier))) {
throw new Error("Prompt does not exist, you must create it first.");
}
Expand All @@ -3869,7 +3876,7 @@
throw await this._ownerConflictError("update a prompt", owner);
}

const payload: Record<string, any> = {};

Check warning on line 3879 in js/src/client.ts

View workflow job for this annotation

GitHub Actions / Check linting

Unexpected any. Specify a different type

if (options?.description !== undefined)
payload.description = options.description;
Expand Down
16 changes: 15 additions & 1 deletion js/src/run_trees.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import * as uuid from "uuid";
import { BaseRun, KVMap, RunCreate, RunUpdate } from "./schemas.js";
import {
Attachments,
BaseRun,
KVMap,
RunCreate,
RunUpdate,
} from "./schemas.js";
import {
RuntimeEnvironment,
getEnvironmentVariable,
Expand Down Expand Up @@ -55,6 +61,7 @@ export interface RunTreeConfig {

trace_id?: string;
dotted_order?: string;
attachments?: Attachments;
}

export interface RunnableConfigLike {
Expand Down Expand Up @@ -172,6 +179,11 @@ export class RunTree implements BaseRun {
tracingEnabled?: boolean;
execution_order: number;
child_execution_order: number;
/**
* Attachments associated with the run.
* Each entry is a tuple of [mime_type, bytes]
*/
attachments?: Attachments;

constructor(originalConfig: RunTreeConfig | RunTree) {
// If you pass in a run tree directly, return a shallow clone
Expand Down Expand Up @@ -370,6 +382,7 @@ export class RunTree implements BaseRun {
trace_id: run.trace_id,
dotted_order: run.dotted_order,
tags: run.tags,
attachments: run.attachments,
};
return persistedRun;
}
Expand Down Expand Up @@ -407,6 +420,7 @@ export class RunTree implements BaseRun {
dotted_order: this.dotted_order,
trace_id: this.trace_id,
tags: this.tags,
attachments: this.attachments,
};

await this.client.updateRun(this.id, runUpdate);
Expand Down
11 changes: 10 additions & 1 deletion js/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export interface BaseExample {
source_run_id?: string;
}

export type AttachmentData = Uint8Array | ArrayBuffer;
export type Attachments = Record<string, [string, AttachmentData]>;

/**
* A run can represent either a trace (root run)
* or a child run (~span).
Expand Down Expand Up @@ -131,7 +134,7 @@ export interface BaseRun {
* Attachments associated with the run.
* Each entry is a tuple of [mime_type, bytes]
*/
attachments?: Record<string, [string, Uint8Array]>;
attachments?: Attachments;
}

type S3URL = {
Expand Down Expand Up @@ -231,6 +234,12 @@ export interface RunUpdate {
* - 20230915T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155650Zc8d9f4c5-6c5a-4b2d-9b1c-3d9d7a7c5c7c
*/
dotted_order?: string;

/**
* Attachments associated with the run.
* Each entry is a tuple of [mime_type, bytes]
*/
attachments?: Attachments;
}

export interface ExampleCreate extends BaseExample {
Expand Down
Loading
Loading