langsmith 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +181 -5
- package/dist/client.d.ts +16 -2
- package/dist/client.js +181 -5
- package/dist/evaluation/_runner.cjs +40 -7
- package/dist/evaluation/_runner.d.ts +17 -4
- package/dist/evaluation/_runner.js +40 -7
- package/dist/evaluation/evaluator.cjs +1 -0
- package/dist/evaluation/evaluator.js +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas.d.ts +49 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -533,6 +533,10 @@ class Client {
|
|
|
533
533
|
serverInfo.batch_ingest_config?.size_limit_bytes ??
|
|
534
534
|
exports.DEFAULT_BATCH_SIZE_LIMIT_BYTES);
|
|
535
535
|
}
|
|
536
|
+
async _getMultiPartSupport() {
|
|
537
|
+
const serverInfo = await this._ensureServerInfo();
|
|
538
|
+
return (serverInfo.instance_flags?.dataset_examples_multipart_enabled ?? false);
|
|
539
|
+
}
|
|
536
540
|
drainAutoBatchQueue(batchSizeLimit) {
|
|
537
541
|
while (this.autoBatchQueue.items.length > 0) {
|
|
538
542
|
const [batch, done] = this.autoBatchQueue.pop(batchSizeLimit);
|
|
@@ -830,7 +834,16 @@ class Client {
|
|
|
830
834
|
const attachments = allAttachments[payload.id];
|
|
831
835
|
if (attachments) {
|
|
832
836
|
delete allAttachments[payload.id];
|
|
833
|
-
for (const [name,
|
|
837
|
+
for (const [name, attachment] of Object.entries(attachments)) {
|
|
838
|
+
let contentType;
|
|
839
|
+
let content;
|
|
840
|
+
if (Array.isArray(attachment)) {
|
|
841
|
+
[contentType, content] = attachment;
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
contentType = attachment.mimeType;
|
|
845
|
+
content = attachment.data;
|
|
846
|
+
}
|
|
834
847
|
// Validate that the attachment name doesn't contain a '.'
|
|
835
848
|
if (name.includes(".")) {
|
|
836
849
|
console.warn(`Skipping attachment '${name}' for run ${payload.id}: Invalid attachment name. ` +
|
|
@@ -1938,9 +1951,21 @@ class Client {
|
|
|
1938
1951
|
async readExample(exampleId) {
|
|
1939
1952
|
(0, _uuid_js_1.assertUuid)(exampleId);
|
|
1940
1953
|
const path = `/examples/${exampleId}`;
|
|
1941
|
-
|
|
1954
|
+
const rawExample = await this._get(path);
|
|
1955
|
+
const { attachment_urls, ...rest } = rawExample;
|
|
1956
|
+
const example = rest;
|
|
1957
|
+
if (attachment_urls) {
|
|
1958
|
+
// add attachments back to the example
|
|
1959
|
+
example.attachments = Object.entries(attachment_urls).reduce((acc, [key, value]) => {
|
|
1960
|
+
acc[key.slice("attachment.".length)] = {
|
|
1961
|
+
presigned_url: value.presigned_url,
|
|
1962
|
+
};
|
|
1963
|
+
return acc;
|
|
1964
|
+
}, {});
|
|
1965
|
+
}
|
|
1966
|
+
return example;
|
|
1942
1967
|
}
|
|
1943
|
-
async *listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, } = {}) {
|
|
1968
|
+
async *listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, includeAttachments, } = {}) {
|
|
1944
1969
|
let datasetId_;
|
|
1945
1970
|
if (datasetId !== undefined && datasetName !== undefined) {
|
|
1946
1971
|
throw new Error("Must provide either datasetName or datasetId, not both");
|
|
@@ -1989,9 +2014,22 @@ class Client {
|
|
|
1989
2014
|
if (filter !== undefined) {
|
|
1990
2015
|
params.append("filter", filter);
|
|
1991
2016
|
}
|
|
2017
|
+
if (includeAttachments === true) {
|
|
2018
|
+
["attachment_urls", "outputs", "metadata"].forEach((field) => params.append("select", field));
|
|
2019
|
+
}
|
|
1992
2020
|
let i = 0;
|
|
1993
|
-
for await (const
|
|
1994
|
-
for (const
|
|
2021
|
+
for await (const rawExamples of this._getPaginated("/examples", params)) {
|
|
2022
|
+
for (const rawExample of rawExamples) {
|
|
2023
|
+
const { attachment_urls, ...rest } = rawExample;
|
|
2024
|
+
const example = rest;
|
|
2025
|
+
if (attachment_urls) {
|
|
2026
|
+
example.attachments = Object.entries(attachment_urls).reduce((acc, [key, value]) => {
|
|
2027
|
+
acc[key.slice("attachment.".length)] = {
|
|
2028
|
+
presigned_url: value.presigned_url,
|
|
2029
|
+
};
|
|
2030
|
+
return acc;
|
|
2031
|
+
}, {});
|
|
2032
|
+
}
|
|
1995
2033
|
yield example;
|
|
1996
2034
|
i++;
|
|
1997
2035
|
}
|
|
@@ -2662,6 +2700,144 @@ class Client {
|
|
|
2662
2700
|
const result = await response.json();
|
|
2663
2701
|
return this._getPromptUrl(`${owner}/${promptName}${result.commit_hash ? `:${result.commit_hash}` : ""}`);
|
|
2664
2702
|
}
|
|
2703
|
+
/**
|
|
2704
|
+
* Update examples with attachments using multipart form data.
|
|
2705
|
+
* @param updates List of ExampleUpdateWithAttachments objects to upsert
|
|
2706
|
+
* @returns Promise with the update response
|
|
2707
|
+
*/
|
|
2708
|
+
async updateExamplesMultipart(datasetId, updates = []) {
|
|
2709
|
+
if (!(await this._getMultiPartSupport())) {
|
|
2710
|
+
throw new Error("Your LangSmith version does not allow using the multipart examples endpoint, please update to the latest version.");
|
|
2711
|
+
}
|
|
2712
|
+
const formData = new FormData();
|
|
2713
|
+
for (const example of updates) {
|
|
2714
|
+
const exampleId = example.id;
|
|
2715
|
+
// Prepare the main example body
|
|
2716
|
+
const exampleBody = {
|
|
2717
|
+
...(example.metadata && { metadata: example.metadata }),
|
|
2718
|
+
...(example.split && { split: example.split }),
|
|
2719
|
+
};
|
|
2720
|
+
// Add main example data
|
|
2721
|
+
const stringifiedExample = (0, index_js_2.stringify)(exampleBody);
|
|
2722
|
+
const exampleBlob = new Blob([stringifiedExample], {
|
|
2723
|
+
type: "application/json",
|
|
2724
|
+
});
|
|
2725
|
+
formData.append(exampleId, exampleBlob);
|
|
2726
|
+
// Add inputs
|
|
2727
|
+
if (example.inputs) {
|
|
2728
|
+
const stringifiedInputs = (0, index_js_2.stringify)(example.inputs);
|
|
2729
|
+
const inputsBlob = new Blob([stringifiedInputs], {
|
|
2730
|
+
type: "application/json",
|
|
2731
|
+
});
|
|
2732
|
+
formData.append(`${exampleId}.inputs`, inputsBlob);
|
|
2733
|
+
}
|
|
2734
|
+
// Add outputs if present
|
|
2735
|
+
if (example.outputs) {
|
|
2736
|
+
const stringifiedOutputs = (0, index_js_2.stringify)(example.outputs);
|
|
2737
|
+
const outputsBlob = new Blob([stringifiedOutputs], {
|
|
2738
|
+
type: "application/json",
|
|
2739
|
+
});
|
|
2740
|
+
formData.append(`${exampleId}.outputs`, outputsBlob);
|
|
2741
|
+
}
|
|
2742
|
+
// Add attachments if present
|
|
2743
|
+
if (example.attachments) {
|
|
2744
|
+
for (const [name, attachment] of Object.entries(example.attachments)) {
|
|
2745
|
+
let mimeType;
|
|
2746
|
+
let data;
|
|
2747
|
+
if (Array.isArray(attachment)) {
|
|
2748
|
+
[mimeType, data] = attachment;
|
|
2749
|
+
}
|
|
2750
|
+
else {
|
|
2751
|
+
mimeType = attachment.mimeType;
|
|
2752
|
+
data = attachment.data;
|
|
2753
|
+
}
|
|
2754
|
+
const attachmentBlob = new Blob([data], {
|
|
2755
|
+
type: `${mimeType}; length=${data.byteLength}`,
|
|
2756
|
+
});
|
|
2757
|
+
formData.append(`${exampleId}.attachment.${name}`, attachmentBlob);
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
if (example.attachments_operations) {
|
|
2761
|
+
const stringifiedAttachmentsOperations = (0, index_js_2.stringify)(example.attachments_operations);
|
|
2762
|
+
const attachmentsOperationsBlob = new Blob([stringifiedAttachmentsOperations], {
|
|
2763
|
+
type: "application/json",
|
|
2764
|
+
});
|
|
2765
|
+
formData.append(`${exampleId}.attachments_operations`, attachmentsOperationsBlob);
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
const response = await this.caller.call((0, fetch_js_1._getFetchImplementation)(), `${this.apiUrl}/v1/platform/datasets/${datasetId}/examples`, {
|
|
2769
|
+
method: "PATCH",
|
|
2770
|
+
headers: this.headers,
|
|
2771
|
+
body: formData,
|
|
2772
|
+
});
|
|
2773
|
+
const result = await response.json();
|
|
2774
|
+
return result;
|
|
2775
|
+
}
|
|
2776
|
+
/**
|
|
2777
|
+
* Upload examples with attachments using multipart form data.
|
|
2778
|
+
* @param uploads List of ExampleUploadWithAttachments objects to upload
|
|
2779
|
+
* @returns Promise with the upload response
|
|
2780
|
+
*/
|
|
2781
|
+
async uploadExamplesMultipart(datasetId, uploads = []) {
|
|
2782
|
+
if (!(await this._getMultiPartSupport())) {
|
|
2783
|
+
throw new Error("Your LangSmith version does not allow using the multipart examples endpoint, please update to the latest version.");
|
|
2784
|
+
}
|
|
2785
|
+
const formData = new FormData();
|
|
2786
|
+
for (const example of uploads) {
|
|
2787
|
+
const exampleId = (example.id ?? uuid.v4()).toString();
|
|
2788
|
+
// Prepare the main example body
|
|
2789
|
+
const exampleBody = {
|
|
2790
|
+
created_at: example.created_at,
|
|
2791
|
+
...(example.metadata && { metadata: example.metadata }),
|
|
2792
|
+
...(example.split && { split: example.split }),
|
|
2793
|
+
};
|
|
2794
|
+
// Add main example data
|
|
2795
|
+
const stringifiedExample = (0, index_js_2.stringify)(exampleBody);
|
|
2796
|
+
const exampleBlob = new Blob([stringifiedExample], {
|
|
2797
|
+
type: "application/json",
|
|
2798
|
+
});
|
|
2799
|
+
formData.append(exampleId, exampleBlob);
|
|
2800
|
+
// Add inputs
|
|
2801
|
+
const stringifiedInputs = (0, index_js_2.stringify)(example.inputs);
|
|
2802
|
+
const inputsBlob = new Blob([stringifiedInputs], {
|
|
2803
|
+
type: "application/json",
|
|
2804
|
+
});
|
|
2805
|
+
formData.append(`${exampleId}.inputs`, inputsBlob);
|
|
2806
|
+
// Add outputs if present
|
|
2807
|
+
if (example.outputs) {
|
|
2808
|
+
const stringifiedOutputs = (0, index_js_2.stringify)(example.outputs);
|
|
2809
|
+
const outputsBlob = new Blob([stringifiedOutputs], {
|
|
2810
|
+
type: "application/json",
|
|
2811
|
+
});
|
|
2812
|
+
formData.append(`${exampleId}.outputs`, outputsBlob);
|
|
2813
|
+
}
|
|
2814
|
+
// Add attachments if present
|
|
2815
|
+
if (example.attachments) {
|
|
2816
|
+
for (const [name, attachment] of Object.entries(example.attachments)) {
|
|
2817
|
+
let mimeType;
|
|
2818
|
+
let data;
|
|
2819
|
+
if (Array.isArray(attachment)) {
|
|
2820
|
+
[mimeType, data] = attachment;
|
|
2821
|
+
}
|
|
2822
|
+
else {
|
|
2823
|
+
mimeType = attachment.mimeType;
|
|
2824
|
+
data = attachment.data;
|
|
2825
|
+
}
|
|
2826
|
+
const attachmentBlob = new Blob([data], {
|
|
2827
|
+
type: `${mimeType}; length=${data.byteLength}`,
|
|
2828
|
+
});
|
|
2829
|
+
formData.append(`${exampleId}.attachment.${name}`, attachmentBlob);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
const response = await this.caller.call((0, fetch_js_1._getFetchImplementation)(), `${this.apiUrl}/v1/platform/datasets/${datasetId}/examples`, {
|
|
2834
|
+
method: "POST",
|
|
2835
|
+
headers: this.headers,
|
|
2836
|
+
body: formData,
|
|
2837
|
+
});
|
|
2838
|
+
const result = await response.json();
|
|
2839
|
+
return result;
|
|
2840
|
+
}
|
|
2665
2841
|
async updatePrompt(promptIdentifier, options) {
|
|
2666
2842
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
2667
2843
|
throw new Error("Prompt does not exist, you must create it first.");
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AsyncCallerParams } from "./utils/async_caller.js";
|
|
2
|
-
import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments } from "./schemas.js";
|
|
2
|
+
import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments, ExampleUploadWithAttachments, UploadExamplesResponse, ExampleUpdateWithAttachments, UpdateExamplesResponse } from "./schemas.js";
|
|
3
3
|
import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluation/evaluator.js";
|
|
4
4
|
export interface ClientConfig {
|
|
5
5
|
apiUrl?: string;
|
|
@@ -226,6 +226,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
226
226
|
private _getCursorPaginatedList;
|
|
227
227
|
private _filterForSampling;
|
|
228
228
|
private _getBatchSizeLimitBytes;
|
|
229
|
+
private _getMultiPartSupport;
|
|
229
230
|
private drainAutoBatchQueue;
|
|
230
231
|
private _processBatch;
|
|
231
232
|
private processRunOperation;
|
|
@@ -531,7 +532,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
531
532
|
createLLMExample(input: string, generation: string | undefined, options: CreateExampleOptions): Promise<Example>;
|
|
532
533
|
createChatExample(input: KVMap[] | LangChainBaseMessage[], generations: KVMap | LangChainBaseMessage | undefined, options: CreateExampleOptions): Promise<Example>;
|
|
533
534
|
readExample(exampleId: string): Promise<Example>;
|
|
534
|
-
listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, }?: {
|
|
535
|
+
listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, includeAttachments, }?: {
|
|
535
536
|
datasetId?: string;
|
|
536
537
|
datasetName?: string;
|
|
537
538
|
exampleIds?: string[];
|
|
@@ -542,6 +543,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
542
543
|
limit?: number;
|
|
543
544
|
offset?: number;
|
|
544
545
|
filter?: string;
|
|
546
|
+
includeAttachments?: boolean;
|
|
545
547
|
}): AsyncIterable<Example>;
|
|
546
548
|
deleteExample(exampleId: string): Promise<void>;
|
|
547
549
|
updateExample(exampleId: string, update: ExampleUpdate): Promise<object>;
|
|
@@ -726,6 +728,18 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
726
728
|
createCommit(promptIdentifier: string, object: any, options?: {
|
|
727
729
|
parentCommitHash?: string;
|
|
728
730
|
}): Promise<string>;
|
|
731
|
+
/**
|
|
732
|
+
* Update examples with attachments using multipart form data.
|
|
733
|
+
* @param updates List of ExampleUpdateWithAttachments objects to upsert
|
|
734
|
+
* @returns Promise with the update response
|
|
735
|
+
*/
|
|
736
|
+
updateExamplesMultipart(datasetId: string, updates?: ExampleUpdateWithAttachments[]): Promise<UpdateExamplesResponse>;
|
|
737
|
+
/**
|
|
738
|
+
* Upload examples with attachments using multipart form data.
|
|
739
|
+
* @param uploads List of ExampleUploadWithAttachments objects to upload
|
|
740
|
+
* @returns Promise with the upload response
|
|
741
|
+
*/
|
|
742
|
+
uploadExamplesMultipart(datasetId: string, uploads?: ExampleUploadWithAttachments[]): Promise<UploadExamplesResponse>;
|
|
729
743
|
updatePrompt(promptIdentifier: string, options?: {
|
|
730
744
|
description?: string;
|
|
731
745
|
readme?: string;
|
package/dist/client.js
CHANGED
|
@@ -505,6 +505,10 @@ export class Client {
|
|
|
505
505
|
serverInfo.batch_ingest_config?.size_limit_bytes ??
|
|
506
506
|
DEFAULT_BATCH_SIZE_LIMIT_BYTES);
|
|
507
507
|
}
|
|
508
|
+
async _getMultiPartSupport() {
|
|
509
|
+
const serverInfo = await this._ensureServerInfo();
|
|
510
|
+
return (serverInfo.instance_flags?.dataset_examples_multipart_enabled ?? false);
|
|
511
|
+
}
|
|
508
512
|
drainAutoBatchQueue(batchSizeLimit) {
|
|
509
513
|
while (this.autoBatchQueue.items.length > 0) {
|
|
510
514
|
const [batch, done] = this.autoBatchQueue.pop(batchSizeLimit);
|
|
@@ -802,7 +806,16 @@ export class Client {
|
|
|
802
806
|
const attachments = allAttachments[payload.id];
|
|
803
807
|
if (attachments) {
|
|
804
808
|
delete allAttachments[payload.id];
|
|
805
|
-
for (const [name,
|
|
809
|
+
for (const [name, attachment] of Object.entries(attachments)) {
|
|
810
|
+
let contentType;
|
|
811
|
+
let content;
|
|
812
|
+
if (Array.isArray(attachment)) {
|
|
813
|
+
[contentType, content] = attachment;
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
contentType = attachment.mimeType;
|
|
817
|
+
content = attachment.data;
|
|
818
|
+
}
|
|
806
819
|
// Validate that the attachment name doesn't contain a '.'
|
|
807
820
|
if (name.includes(".")) {
|
|
808
821
|
console.warn(`Skipping attachment '${name}' for run ${payload.id}: Invalid attachment name. ` +
|
|
@@ -1910,9 +1923,21 @@ export class Client {
|
|
|
1910
1923
|
async readExample(exampleId) {
|
|
1911
1924
|
assertUuid(exampleId);
|
|
1912
1925
|
const path = `/examples/${exampleId}`;
|
|
1913
|
-
|
|
1926
|
+
const rawExample = await this._get(path);
|
|
1927
|
+
const { attachment_urls, ...rest } = rawExample;
|
|
1928
|
+
const example = rest;
|
|
1929
|
+
if (attachment_urls) {
|
|
1930
|
+
// add attachments back to the example
|
|
1931
|
+
example.attachments = Object.entries(attachment_urls).reduce((acc, [key, value]) => {
|
|
1932
|
+
acc[key.slice("attachment.".length)] = {
|
|
1933
|
+
presigned_url: value.presigned_url,
|
|
1934
|
+
};
|
|
1935
|
+
return acc;
|
|
1936
|
+
}, {});
|
|
1937
|
+
}
|
|
1938
|
+
return example;
|
|
1914
1939
|
}
|
|
1915
|
-
async *listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, } = {}) {
|
|
1940
|
+
async *listExamples({ datasetId, datasetName, exampleIds, asOf, splits, inlineS3Urls, metadata, limit, offset, filter, includeAttachments, } = {}) {
|
|
1916
1941
|
let datasetId_;
|
|
1917
1942
|
if (datasetId !== undefined && datasetName !== undefined) {
|
|
1918
1943
|
throw new Error("Must provide either datasetName or datasetId, not both");
|
|
@@ -1961,9 +1986,22 @@ export class Client {
|
|
|
1961
1986
|
if (filter !== undefined) {
|
|
1962
1987
|
params.append("filter", filter);
|
|
1963
1988
|
}
|
|
1989
|
+
if (includeAttachments === true) {
|
|
1990
|
+
["attachment_urls", "outputs", "metadata"].forEach((field) => params.append("select", field));
|
|
1991
|
+
}
|
|
1964
1992
|
let i = 0;
|
|
1965
|
-
for await (const
|
|
1966
|
-
for (const
|
|
1993
|
+
for await (const rawExamples of this._getPaginated("/examples", params)) {
|
|
1994
|
+
for (const rawExample of rawExamples) {
|
|
1995
|
+
const { attachment_urls, ...rest } = rawExample;
|
|
1996
|
+
const example = rest;
|
|
1997
|
+
if (attachment_urls) {
|
|
1998
|
+
example.attachments = Object.entries(attachment_urls).reduce((acc, [key, value]) => {
|
|
1999
|
+
acc[key.slice("attachment.".length)] = {
|
|
2000
|
+
presigned_url: value.presigned_url,
|
|
2001
|
+
};
|
|
2002
|
+
return acc;
|
|
2003
|
+
}, {});
|
|
2004
|
+
}
|
|
1967
2005
|
yield example;
|
|
1968
2006
|
i++;
|
|
1969
2007
|
}
|
|
@@ -2634,6 +2672,144 @@ export class Client {
|
|
|
2634
2672
|
const result = await response.json();
|
|
2635
2673
|
return this._getPromptUrl(`${owner}/${promptName}${result.commit_hash ? `:${result.commit_hash}` : ""}`);
|
|
2636
2674
|
}
|
|
2675
|
+
/**
|
|
2676
|
+
* Update examples with attachments using multipart form data.
|
|
2677
|
+
* @param updates List of ExampleUpdateWithAttachments objects to upsert
|
|
2678
|
+
* @returns Promise with the update response
|
|
2679
|
+
*/
|
|
2680
|
+
async updateExamplesMultipart(datasetId, updates = []) {
|
|
2681
|
+
if (!(await this._getMultiPartSupport())) {
|
|
2682
|
+
throw new Error("Your LangSmith version does not allow using the multipart examples endpoint, please update to the latest version.");
|
|
2683
|
+
}
|
|
2684
|
+
const formData = new FormData();
|
|
2685
|
+
for (const example of updates) {
|
|
2686
|
+
const exampleId = example.id;
|
|
2687
|
+
// Prepare the main example body
|
|
2688
|
+
const exampleBody = {
|
|
2689
|
+
...(example.metadata && { metadata: example.metadata }),
|
|
2690
|
+
...(example.split && { split: example.split }),
|
|
2691
|
+
};
|
|
2692
|
+
// Add main example data
|
|
2693
|
+
const stringifiedExample = stringifyForTracing(exampleBody);
|
|
2694
|
+
const exampleBlob = new Blob([stringifiedExample], {
|
|
2695
|
+
type: "application/json",
|
|
2696
|
+
});
|
|
2697
|
+
formData.append(exampleId, exampleBlob);
|
|
2698
|
+
// Add inputs
|
|
2699
|
+
if (example.inputs) {
|
|
2700
|
+
const stringifiedInputs = stringifyForTracing(example.inputs);
|
|
2701
|
+
const inputsBlob = new Blob([stringifiedInputs], {
|
|
2702
|
+
type: "application/json",
|
|
2703
|
+
});
|
|
2704
|
+
formData.append(`${exampleId}.inputs`, inputsBlob);
|
|
2705
|
+
}
|
|
2706
|
+
// Add outputs if present
|
|
2707
|
+
if (example.outputs) {
|
|
2708
|
+
const stringifiedOutputs = stringifyForTracing(example.outputs);
|
|
2709
|
+
const outputsBlob = new Blob([stringifiedOutputs], {
|
|
2710
|
+
type: "application/json",
|
|
2711
|
+
});
|
|
2712
|
+
formData.append(`${exampleId}.outputs`, outputsBlob);
|
|
2713
|
+
}
|
|
2714
|
+
// Add attachments if present
|
|
2715
|
+
if (example.attachments) {
|
|
2716
|
+
for (const [name, attachment] of Object.entries(example.attachments)) {
|
|
2717
|
+
let mimeType;
|
|
2718
|
+
let data;
|
|
2719
|
+
if (Array.isArray(attachment)) {
|
|
2720
|
+
[mimeType, data] = attachment;
|
|
2721
|
+
}
|
|
2722
|
+
else {
|
|
2723
|
+
mimeType = attachment.mimeType;
|
|
2724
|
+
data = attachment.data;
|
|
2725
|
+
}
|
|
2726
|
+
const attachmentBlob = new Blob([data], {
|
|
2727
|
+
type: `${mimeType}; length=${data.byteLength}`,
|
|
2728
|
+
});
|
|
2729
|
+
formData.append(`${exampleId}.attachment.${name}`, attachmentBlob);
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
if (example.attachments_operations) {
|
|
2733
|
+
const stringifiedAttachmentsOperations = stringifyForTracing(example.attachments_operations);
|
|
2734
|
+
const attachmentsOperationsBlob = new Blob([stringifiedAttachmentsOperations], {
|
|
2735
|
+
type: "application/json",
|
|
2736
|
+
});
|
|
2737
|
+
formData.append(`${exampleId}.attachments_operations`, attachmentsOperationsBlob);
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
const response = await this.caller.call(_getFetchImplementation(), `${this.apiUrl}/v1/platform/datasets/${datasetId}/examples`, {
|
|
2741
|
+
method: "PATCH",
|
|
2742
|
+
headers: this.headers,
|
|
2743
|
+
body: formData,
|
|
2744
|
+
});
|
|
2745
|
+
const result = await response.json();
|
|
2746
|
+
return result;
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Upload examples with attachments using multipart form data.
|
|
2750
|
+
* @param uploads List of ExampleUploadWithAttachments objects to upload
|
|
2751
|
+
* @returns Promise with the upload response
|
|
2752
|
+
*/
|
|
2753
|
+
async uploadExamplesMultipart(datasetId, uploads = []) {
|
|
2754
|
+
if (!(await this._getMultiPartSupport())) {
|
|
2755
|
+
throw new Error("Your LangSmith version does not allow using the multipart examples endpoint, please update to the latest version.");
|
|
2756
|
+
}
|
|
2757
|
+
const formData = new FormData();
|
|
2758
|
+
for (const example of uploads) {
|
|
2759
|
+
const exampleId = (example.id ?? uuid.v4()).toString();
|
|
2760
|
+
// Prepare the main example body
|
|
2761
|
+
const exampleBody = {
|
|
2762
|
+
created_at: example.created_at,
|
|
2763
|
+
...(example.metadata && { metadata: example.metadata }),
|
|
2764
|
+
...(example.split && { split: example.split }),
|
|
2765
|
+
};
|
|
2766
|
+
// Add main example data
|
|
2767
|
+
const stringifiedExample = stringifyForTracing(exampleBody);
|
|
2768
|
+
const exampleBlob = new Blob([stringifiedExample], {
|
|
2769
|
+
type: "application/json",
|
|
2770
|
+
});
|
|
2771
|
+
formData.append(exampleId, exampleBlob);
|
|
2772
|
+
// Add inputs
|
|
2773
|
+
const stringifiedInputs = stringifyForTracing(example.inputs);
|
|
2774
|
+
const inputsBlob = new Blob([stringifiedInputs], {
|
|
2775
|
+
type: "application/json",
|
|
2776
|
+
});
|
|
2777
|
+
formData.append(`${exampleId}.inputs`, inputsBlob);
|
|
2778
|
+
// Add outputs if present
|
|
2779
|
+
if (example.outputs) {
|
|
2780
|
+
const stringifiedOutputs = stringifyForTracing(example.outputs);
|
|
2781
|
+
const outputsBlob = new Blob([stringifiedOutputs], {
|
|
2782
|
+
type: "application/json",
|
|
2783
|
+
});
|
|
2784
|
+
formData.append(`${exampleId}.outputs`, outputsBlob);
|
|
2785
|
+
}
|
|
2786
|
+
// Add attachments if present
|
|
2787
|
+
if (example.attachments) {
|
|
2788
|
+
for (const [name, attachment] of Object.entries(example.attachments)) {
|
|
2789
|
+
let mimeType;
|
|
2790
|
+
let data;
|
|
2791
|
+
if (Array.isArray(attachment)) {
|
|
2792
|
+
[mimeType, data] = attachment;
|
|
2793
|
+
}
|
|
2794
|
+
else {
|
|
2795
|
+
mimeType = attachment.mimeType;
|
|
2796
|
+
data = attachment.data;
|
|
2797
|
+
}
|
|
2798
|
+
const attachmentBlob = new Blob([data], {
|
|
2799
|
+
type: `${mimeType}; length=${data.byteLength}`,
|
|
2800
|
+
});
|
|
2801
|
+
formData.append(`${exampleId}.attachment.${name}`, attachmentBlob);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
const response = await this.caller.call(_getFetchImplementation(), `${this.apiUrl}/v1/platform/datasets/${datasetId}/examples`, {
|
|
2806
|
+
method: "POST",
|
|
2807
|
+
headers: this.headers,
|
|
2808
|
+
body: formData,
|
|
2809
|
+
});
|
|
2810
|
+
const result = await response.json();
|
|
2811
|
+
return result;
|
|
2812
|
+
}
|
|
2637
2813
|
async updatePrompt(promptIdentifier, options) {
|
|
2638
2814
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
2639
2815
|
throw new Error("Prompt does not exist, you must create it first.");
|
|
@@ -38,7 +38,10 @@ class _ExperimentManager {
|
|
|
38
38
|
if (!this._data) {
|
|
39
39
|
throw new Error("Data not provided in this experiment.");
|
|
40
40
|
}
|
|
41
|
-
const unresolvedData = _resolveData(this._data, {
|
|
41
|
+
const unresolvedData = _resolveData(this._data, {
|
|
42
|
+
client: this.client,
|
|
43
|
+
includeAttachments: this._includeAttachments,
|
|
44
|
+
});
|
|
42
45
|
if (!this._examples) {
|
|
43
46
|
this._examples = [];
|
|
44
47
|
}
|
|
@@ -169,6 +172,12 @@ class _ExperimentManager {
|
|
|
169
172
|
writable: true,
|
|
170
173
|
value: void 0
|
|
171
174
|
});
|
|
175
|
+
Object.defineProperty(this, "_includeAttachments", {
|
|
176
|
+
enumerable: true,
|
|
177
|
+
configurable: true,
|
|
178
|
+
writable: true,
|
|
179
|
+
value: void 0
|
|
180
|
+
});
|
|
172
181
|
this.client = args.client ?? new index_js_1.Client();
|
|
173
182
|
if (!args.experiment) {
|
|
174
183
|
this._experimentName = (0, _random_name_js_1.randomName)();
|
|
@@ -202,6 +211,7 @@ class _ExperimentManager {
|
|
|
202
211
|
this._evaluationResults = args.evaluationResults;
|
|
203
212
|
this._summaryResults = args.summaryResults;
|
|
204
213
|
this._numRepetitions = args.numRepetitions;
|
|
214
|
+
this._includeAttachments = args.includeAttachments;
|
|
205
215
|
}
|
|
206
216
|
_getExperiment() {
|
|
207
217
|
if (!this._experiment) {
|
|
@@ -289,6 +299,7 @@ class _ExperimentManager {
|
|
|
289
299
|
client: this.client,
|
|
290
300
|
evaluationResults: this._evaluationResults,
|
|
291
301
|
summaryResults: this._summaryResults,
|
|
302
|
+
includeAttachments: this._includeAttachments,
|
|
292
303
|
});
|
|
293
304
|
}
|
|
294
305
|
async withPredictions(target, options) {
|
|
@@ -303,6 +314,7 @@ class _ExperimentManager {
|
|
|
303
314
|
yield pred.run;
|
|
304
315
|
}
|
|
305
316
|
})(),
|
|
317
|
+
includeAttachments: this._includeAttachments,
|
|
306
318
|
});
|
|
307
319
|
}
|
|
308
320
|
async withEvaluators(evaluators, options) {
|
|
@@ -325,6 +337,7 @@ class _ExperimentManager {
|
|
|
325
337
|
}
|
|
326
338
|
})(),
|
|
327
339
|
summaryResults: this._summaryResults,
|
|
340
|
+
includeAttachments: this._includeAttachments,
|
|
328
341
|
});
|
|
329
342
|
}
|
|
330
343
|
async withSummaryEvaluators(summaryEvaluators) {
|
|
@@ -338,6 +351,7 @@ class _ExperimentManager {
|
|
|
338
351
|
_runsArray: this._runsArray,
|
|
339
352
|
evaluationResults: this._evaluationResults,
|
|
340
353
|
summaryResults: aggregateFeedbackGen,
|
|
354
|
+
includeAttachments: this._includeAttachments,
|
|
341
355
|
});
|
|
342
356
|
}
|
|
343
357
|
async *getResults() {
|
|
@@ -388,7 +402,7 @@ class _ExperimentManager {
|
|
|
388
402
|
const examples = await this.getExamples();
|
|
389
403
|
if (maxConcurrency === 0) {
|
|
390
404
|
for (const example of examples) {
|
|
391
|
-
yield await _forward(target, example, this.experimentName, this._metadata, this.client);
|
|
405
|
+
yield await _forward(target, example, this.experimentName, this._metadata, this.client, this._includeAttachments);
|
|
392
406
|
}
|
|
393
407
|
}
|
|
394
408
|
else {
|
|
@@ -397,7 +411,7 @@ class _ExperimentManager {
|
|
|
397
411
|
});
|
|
398
412
|
const futures = [];
|
|
399
413
|
for await (const example of examples) {
|
|
400
|
-
futures.push(caller.call(_forward, target, example, this.experimentName, this._metadata, this.client));
|
|
414
|
+
futures.push(caller.call(_forward, target, example, this.experimentName, this._metadata, this.client, this._includeAttachments));
|
|
401
415
|
}
|
|
402
416
|
for await (const future of futures) {
|
|
403
417
|
yield future;
|
|
@@ -659,6 +673,7 @@ async function _evaluate(target, fields) {
|
|
|
659
673
|
experiment: experiment_ ?? fields.experimentPrefix,
|
|
660
674
|
runs: newRuns ?? undefined,
|
|
661
675
|
numRepetitions: fields.numRepetitions ?? 1,
|
|
676
|
+
includeAttachments: standardFields.includeAttachments,
|
|
662
677
|
}).start();
|
|
663
678
|
if (_isCallable(target)) {
|
|
664
679
|
manager = await manager.withPredictions(target, {
|
|
@@ -678,7 +693,7 @@ async function _evaluate(target, fields) {
|
|
|
678
693
|
await results.processData(manager);
|
|
679
694
|
return results;
|
|
680
695
|
}
|
|
681
|
-
async function _forward(fn, example, experimentName, metadata, client) {
|
|
696
|
+
async function _forward(fn, example, experimentName, metadata, client, includeAttachments) {
|
|
682
697
|
let run = null;
|
|
683
698
|
const _getRun = (r) => {
|
|
684
699
|
run = r;
|
|
@@ -708,16 +723,32 @@ async function _forward(fn, example, experimentName, metadata, client) {
|
|
|
708
723
|
// no-op
|
|
709
724
|
}
|
|
710
725
|
// Issue with retrieving LangChain callbacks, rely on interop
|
|
711
|
-
if (langChainCallbacks === undefined) {
|
|
726
|
+
if (langChainCallbacks === undefined && !includeAttachments) {
|
|
712
727
|
return await fn.invoke(inputs);
|
|
713
728
|
}
|
|
714
|
-
else {
|
|
729
|
+
else if (langChainCallbacks === undefined && includeAttachments) {
|
|
730
|
+
return await fn.invoke(inputs, {
|
|
731
|
+
attachments: example.attachments,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
else if (!includeAttachments) {
|
|
715
735
|
return await fn.invoke(inputs, { callbacks: langChainCallbacks });
|
|
716
736
|
}
|
|
737
|
+
else {
|
|
738
|
+
return await fn.invoke(inputs, {
|
|
739
|
+
attachments: example.attachments,
|
|
740
|
+
callbacks: langChainCallbacks,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
717
743
|
}, options)
|
|
718
744
|
: (0, traceable_js_1.traceable)(fn, options);
|
|
719
745
|
try {
|
|
720
|
-
|
|
746
|
+
if (includeAttachments && !("invoke" in fn)) {
|
|
747
|
+
await wrappedFn(example.inputs, { attachments: example.attachments });
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
await wrappedFn(example.inputs);
|
|
751
|
+
}
|
|
721
752
|
}
|
|
722
753
|
catch (e) {
|
|
723
754
|
console.error(`Error running target function: ${e}`);
|
|
@@ -747,11 +778,13 @@ function _resolveData(data, options) {
|
|
|
747
778
|
if (typeof data === "string" && isUUID) {
|
|
748
779
|
return options.client.listExamples({
|
|
749
780
|
datasetId: data,
|
|
781
|
+
includeAttachments: options.includeAttachments,
|
|
750
782
|
});
|
|
751
783
|
}
|
|
752
784
|
if (typeof data === "string") {
|
|
753
785
|
return options.client.listExamples({
|
|
754
786
|
datasetName: data,
|
|
787
|
+
includeAttachments: options.includeAttachments,
|
|
755
788
|
});
|
|
756
789
|
}
|
|
757
790
|
return data;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Client } from "../index.js";
|
|
2
|
-
import { Example, KVMap, Run, TracerSession } from "../schemas.js";
|
|
2
|
+
import { AttachmentInfo, Example, KVMap, Run, TracerSession } from "../schemas.js";
|
|
3
3
|
import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluator.js";
|
|
4
4
|
import { ComparisonEvaluationResults, ComparativeEvaluator } from "./evaluate_comparative.js";
|
|
5
|
-
type
|
|
6
|
-
|
|
5
|
+
export type TargetConfigT = KVMap & {
|
|
6
|
+
attachments?: Record<string, AttachmentInfo>;
|
|
7
|
+
callbacks?: any;
|
|
8
|
+
};
|
|
9
|
+
type StandardTargetT<TInput = any, TOutput = KVMap> = ((input: TInput, config?: TargetConfigT) => Promise<TOutput>) | ((input: TInput, config?: TargetConfigT) => TOutput) | {
|
|
10
|
+
invoke: (input: TInput, config?: TargetConfigT) => TOutput;
|
|
7
11
|
} | {
|
|
8
|
-
invoke: (input: TInput, config?:
|
|
12
|
+
invoke: (input: TInput, config?: TargetConfigT) => Promise<TOutput>;
|
|
9
13
|
};
|
|
10
14
|
type ComparativeTargetT = Array<string> | Array<Promise<ExperimentResults> | ExperimentResults>;
|
|
11
15
|
export type TargetT<TInput = any, TOutput = KVMap> = StandardTargetT<TInput, TOutput> | ComparativeTargetT;
|
|
@@ -39,12 +43,14 @@ export type EvaluatorT = DeprecatedRunEvaluator | DeprecatedFunctionEvaluator |
|
|
|
39
43
|
inputs: Record<string, any>;
|
|
40
44
|
outputs: Record<string, any>;
|
|
41
45
|
referenceOutputs?: Record<string, any>;
|
|
46
|
+
attachments?: Record<string, any>;
|
|
42
47
|
}) => EvaluationResult | EvaluationResults) | ((args: {
|
|
43
48
|
run: Run;
|
|
44
49
|
example: Example;
|
|
45
50
|
inputs: Record<string, any>;
|
|
46
51
|
outputs: Record<string, any>;
|
|
47
52
|
referenceOutputs?: Record<string, any>;
|
|
53
|
+
attachments?: Record<string, any>;
|
|
48
54
|
}) => Promise<EvaluationResult | EvaluationResults>);
|
|
49
55
|
interface _ForwardResults {
|
|
50
56
|
run: Run;
|
|
@@ -61,6 +67,7 @@ interface _ExperimentManagerArgs {
|
|
|
61
67
|
examples?: Example[];
|
|
62
68
|
numRepetitions?: number;
|
|
63
69
|
_runsArray?: Run[];
|
|
70
|
+
includeAttachments?: boolean;
|
|
64
71
|
}
|
|
65
72
|
type BaseEvaluateOptions = {
|
|
66
73
|
/**
|
|
@@ -110,6 +117,11 @@ export interface EvaluateOptions extends BaseEvaluateOptions {
|
|
|
110
117
|
* examples, or a generator of examples.
|
|
111
118
|
*/
|
|
112
119
|
data: DataT;
|
|
120
|
+
/**
|
|
121
|
+
* Whether to use attachments for the experiment.
|
|
122
|
+
* @default false
|
|
123
|
+
*/
|
|
124
|
+
includeAttachments?: boolean;
|
|
113
125
|
}
|
|
114
126
|
export interface ComparativeEvaluateOptions extends BaseEvaluateOptions {
|
|
115
127
|
/**
|
|
@@ -153,6 +165,7 @@ export declare class _ExperimentManager {
|
|
|
153
165
|
_experimentName: string;
|
|
154
166
|
_metadata: KVMap;
|
|
155
167
|
_description?: string;
|
|
168
|
+
_includeAttachments?: boolean;
|
|
156
169
|
get experimentName(): string;
|
|
157
170
|
getExamples(): Promise<Array<Example>>;
|
|
158
171
|
setExamples(examples: Example[]): void;
|
|
@@ -34,7 +34,10 @@ export class _ExperimentManager {
|
|
|
34
34
|
if (!this._data) {
|
|
35
35
|
throw new Error("Data not provided in this experiment.");
|
|
36
36
|
}
|
|
37
|
-
const unresolvedData = _resolveData(this._data, {
|
|
37
|
+
const unresolvedData = _resolveData(this._data, {
|
|
38
|
+
client: this.client,
|
|
39
|
+
includeAttachments: this._includeAttachments,
|
|
40
|
+
});
|
|
38
41
|
if (!this._examples) {
|
|
39
42
|
this._examples = [];
|
|
40
43
|
}
|
|
@@ -165,6 +168,12 @@ export class _ExperimentManager {
|
|
|
165
168
|
writable: true,
|
|
166
169
|
value: void 0
|
|
167
170
|
});
|
|
171
|
+
Object.defineProperty(this, "_includeAttachments", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
writable: true,
|
|
175
|
+
value: void 0
|
|
176
|
+
});
|
|
168
177
|
this.client = args.client ?? new Client();
|
|
169
178
|
if (!args.experiment) {
|
|
170
179
|
this._experimentName = randomName();
|
|
@@ -198,6 +207,7 @@ export class _ExperimentManager {
|
|
|
198
207
|
this._evaluationResults = args.evaluationResults;
|
|
199
208
|
this._summaryResults = args.summaryResults;
|
|
200
209
|
this._numRepetitions = args.numRepetitions;
|
|
210
|
+
this._includeAttachments = args.includeAttachments;
|
|
201
211
|
}
|
|
202
212
|
_getExperiment() {
|
|
203
213
|
if (!this._experiment) {
|
|
@@ -285,6 +295,7 @@ export class _ExperimentManager {
|
|
|
285
295
|
client: this.client,
|
|
286
296
|
evaluationResults: this._evaluationResults,
|
|
287
297
|
summaryResults: this._summaryResults,
|
|
298
|
+
includeAttachments: this._includeAttachments,
|
|
288
299
|
});
|
|
289
300
|
}
|
|
290
301
|
async withPredictions(target, options) {
|
|
@@ -299,6 +310,7 @@ export class _ExperimentManager {
|
|
|
299
310
|
yield pred.run;
|
|
300
311
|
}
|
|
301
312
|
})(),
|
|
313
|
+
includeAttachments: this._includeAttachments,
|
|
302
314
|
});
|
|
303
315
|
}
|
|
304
316
|
async withEvaluators(evaluators, options) {
|
|
@@ -321,6 +333,7 @@ export class _ExperimentManager {
|
|
|
321
333
|
}
|
|
322
334
|
})(),
|
|
323
335
|
summaryResults: this._summaryResults,
|
|
336
|
+
includeAttachments: this._includeAttachments,
|
|
324
337
|
});
|
|
325
338
|
}
|
|
326
339
|
async withSummaryEvaluators(summaryEvaluators) {
|
|
@@ -334,6 +347,7 @@ export class _ExperimentManager {
|
|
|
334
347
|
_runsArray: this._runsArray,
|
|
335
348
|
evaluationResults: this._evaluationResults,
|
|
336
349
|
summaryResults: aggregateFeedbackGen,
|
|
350
|
+
includeAttachments: this._includeAttachments,
|
|
337
351
|
});
|
|
338
352
|
}
|
|
339
353
|
async *getResults() {
|
|
@@ -384,7 +398,7 @@ export class _ExperimentManager {
|
|
|
384
398
|
const examples = await this.getExamples();
|
|
385
399
|
if (maxConcurrency === 0) {
|
|
386
400
|
for (const example of examples) {
|
|
387
|
-
yield await _forward(target, example, this.experimentName, this._metadata, this.client);
|
|
401
|
+
yield await _forward(target, example, this.experimentName, this._metadata, this.client, this._includeAttachments);
|
|
388
402
|
}
|
|
389
403
|
}
|
|
390
404
|
else {
|
|
@@ -393,7 +407,7 @@ export class _ExperimentManager {
|
|
|
393
407
|
});
|
|
394
408
|
const futures = [];
|
|
395
409
|
for await (const example of examples) {
|
|
396
|
-
futures.push(caller.call(_forward, target, example, this.experimentName, this._metadata, this.client));
|
|
410
|
+
futures.push(caller.call(_forward, target, example, this.experimentName, this._metadata, this.client, this._includeAttachments));
|
|
397
411
|
}
|
|
398
412
|
for await (const future of futures) {
|
|
399
413
|
yield future;
|
|
@@ -654,6 +668,7 @@ async function _evaluate(target, fields) {
|
|
|
654
668
|
experiment: experiment_ ?? fields.experimentPrefix,
|
|
655
669
|
runs: newRuns ?? undefined,
|
|
656
670
|
numRepetitions: fields.numRepetitions ?? 1,
|
|
671
|
+
includeAttachments: standardFields.includeAttachments,
|
|
657
672
|
}).start();
|
|
658
673
|
if (_isCallable(target)) {
|
|
659
674
|
manager = await manager.withPredictions(target, {
|
|
@@ -673,7 +688,7 @@ async function _evaluate(target, fields) {
|
|
|
673
688
|
await results.processData(manager);
|
|
674
689
|
return results;
|
|
675
690
|
}
|
|
676
|
-
async function _forward(fn, example, experimentName, metadata, client) {
|
|
691
|
+
async function _forward(fn, example, experimentName, metadata, client, includeAttachments) {
|
|
677
692
|
let run = null;
|
|
678
693
|
const _getRun = (r) => {
|
|
679
694
|
run = r;
|
|
@@ -703,16 +718,32 @@ async function _forward(fn, example, experimentName, metadata, client) {
|
|
|
703
718
|
// no-op
|
|
704
719
|
}
|
|
705
720
|
// Issue with retrieving LangChain callbacks, rely on interop
|
|
706
|
-
if (langChainCallbacks === undefined) {
|
|
721
|
+
if (langChainCallbacks === undefined && !includeAttachments) {
|
|
707
722
|
return await fn.invoke(inputs);
|
|
708
723
|
}
|
|
709
|
-
else {
|
|
724
|
+
else if (langChainCallbacks === undefined && includeAttachments) {
|
|
725
|
+
return await fn.invoke(inputs, {
|
|
726
|
+
attachments: example.attachments,
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
else if (!includeAttachments) {
|
|
710
730
|
return await fn.invoke(inputs, { callbacks: langChainCallbacks });
|
|
711
731
|
}
|
|
732
|
+
else {
|
|
733
|
+
return await fn.invoke(inputs, {
|
|
734
|
+
attachments: example.attachments,
|
|
735
|
+
callbacks: langChainCallbacks,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
712
738
|
}, options)
|
|
713
739
|
: traceable(fn, options);
|
|
714
740
|
try {
|
|
715
|
-
|
|
741
|
+
if (includeAttachments && !("invoke" in fn)) {
|
|
742
|
+
await wrappedFn(example.inputs, { attachments: example.attachments });
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
await wrappedFn(example.inputs);
|
|
746
|
+
}
|
|
716
747
|
}
|
|
717
748
|
catch (e) {
|
|
718
749
|
console.error(`Error running target function: ${e}`);
|
|
@@ -742,11 +773,13 @@ function _resolveData(data, options) {
|
|
|
742
773
|
if (typeof data === "string" && isUUID) {
|
|
743
774
|
return options.client.listExamples({
|
|
744
775
|
datasetId: data,
|
|
776
|
+
includeAttachments: options.includeAttachments,
|
|
745
777
|
});
|
|
746
778
|
}
|
|
747
779
|
if (typeof data === "string") {
|
|
748
780
|
return options.client.listExamples({
|
|
749
781
|
datasetName: data,
|
|
782
|
+
includeAttachments: options.includeAttachments,
|
|
750
783
|
});
|
|
751
784
|
}
|
|
752
785
|
return data;
|
package/dist/index.cjs
CHANGED
|
@@ -8,4 +8,4 @@ Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () {
|
|
|
8
8
|
var fetch_js_1 = require("./singletons/fetch.cjs");
|
|
9
9
|
Object.defineProperty(exports, "overrideFetchImplementation", { enumerable: true, get: function () { return fetch_js_1.overrideFetchImplementation; } });
|
|
10
10
|
// Update using yarn bump-version
|
|
11
|
-
exports.__version__ = "0.2.
|
|
11
|
+
exports.__version__ = "0.2.13";
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { Client, type ClientConfig, type LangSmithTracingClientInterface, } from
|
|
|
2
2
|
export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, } from "./schemas.js";
|
|
3
3
|
export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
4
4
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
5
|
-
export declare const __version__ = "0.2.
|
|
5
|
+
export declare const __version__ = "0.2.13";
|
package/dist/index.js
CHANGED
package/dist/schemas.d.ts
CHANGED
|
@@ -32,8 +32,18 @@ export interface BaseExample {
|
|
|
32
32
|
metadata?: KVMap;
|
|
33
33
|
source_run_id?: string;
|
|
34
34
|
}
|
|
35
|
+
export interface AttachmentInfo {
|
|
36
|
+
presigned_url: string;
|
|
37
|
+
}
|
|
35
38
|
export type AttachmentData = Uint8Array | ArrayBuffer;
|
|
36
|
-
export type
|
|
39
|
+
export type AttachmentDescription = {
|
|
40
|
+
mimeType: string;
|
|
41
|
+
data: AttachmentData;
|
|
42
|
+
};
|
|
43
|
+
export type Attachments = Record<string, [
|
|
44
|
+
string,
|
|
45
|
+
AttachmentData
|
|
46
|
+
] | AttachmentDescription>;
|
|
37
47
|
/**
|
|
38
48
|
* A run can represent either a trace (root run)
|
|
39
49
|
* or a child run (~span).
|
|
@@ -177,12 +187,50 @@ export interface ExampleCreate extends BaseExample {
|
|
|
177
187
|
created_at?: string;
|
|
178
188
|
split?: string | string[];
|
|
179
189
|
}
|
|
190
|
+
export interface ExampleUploadWithAttachments {
|
|
191
|
+
id?: string;
|
|
192
|
+
inputs: KVMap;
|
|
193
|
+
outputs?: KVMap;
|
|
194
|
+
metadata?: KVMap;
|
|
195
|
+
split?: string | string[];
|
|
196
|
+
attachments?: Attachments;
|
|
197
|
+
created_at?: string;
|
|
198
|
+
}
|
|
199
|
+
export interface ExampleUpdateWithAttachments {
|
|
200
|
+
id: string;
|
|
201
|
+
inputs?: KVMap;
|
|
202
|
+
outputs?: KVMap;
|
|
203
|
+
metadata?: KVMap;
|
|
204
|
+
split?: string | string[];
|
|
205
|
+
attachments?: Attachments;
|
|
206
|
+
attachments_operations?: KVMap;
|
|
207
|
+
}
|
|
208
|
+
export interface UploadExamplesResponse {
|
|
209
|
+
count: number;
|
|
210
|
+
example_ids: string[];
|
|
211
|
+
}
|
|
212
|
+
export interface UpdateExamplesResponse extends UploadExamplesResponse {
|
|
213
|
+
}
|
|
180
214
|
export interface Example extends BaseExample {
|
|
215
|
+
id: string;
|
|
216
|
+
created_at: string;
|
|
217
|
+
modified_at?: string;
|
|
218
|
+
source_run_id?: string;
|
|
219
|
+
runs: Run[];
|
|
220
|
+
attachments?: Record<string, AttachmentInfo>;
|
|
221
|
+
split?: string | string[];
|
|
222
|
+
}
|
|
223
|
+
interface RawAttachmentInfo {
|
|
224
|
+
presigned_url: string;
|
|
225
|
+
s3_url: string;
|
|
226
|
+
}
|
|
227
|
+
export interface RawExample extends BaseExample {
|
|
181
228
|
id: string;
|
|
182
229
|
created_at: string;
|
|
183
230
|
modified_at: string;
|
|
184
231
|
source_run_id?: string;
|
|
185
232
|
runs: Run[];
|
|
233
|
+
attachment_urls?: Record<string, RawAttachmentInfo>;
|
|
186
234
|
}
|
|
187
235
|
export interface ExampleUpdate {
|
|
188
236
|
dataset_id?: string;
|