From 5f171219939f6b59a40c6aa77ab1087a0fa25036 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Fri, 8 Nov 2024 00:10:52 -0800 Subject: [PATCH] fix(js): Use batch endpoint instead of individual run endpoint in case of server info fetch failure (#1189) CC @akira --- js/src/client.ts | 18 +--------------- js/src/tests/batch_client.test.ts | 34 ++++++++++++++++++------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/js/src/client.ts b/js/src/client.ts index a1eb830d6..8c094e7fd 100644 --- a/js/src/client.ts +++ b/js/src/client.ts @@ -838,7 +838,7 @@ export class Client { this._serverInfo = await this._getServerInfo(); } catch (e) { console.warn( - `[WARNING]: LangSmith failed to fetch info on supported operations. Falling back to single calls and default limits.` + `[WARNING]: LangSmith failed to fetch info on supported operations. Falling back to batch operations and default limits.` ); } } @@ -956,22 +956,6 @@ export class Client { if (!rawBatch.post.length && !rawBatch.patch.length) { return; } - const serverInfo = await this._ensureServerInfo(); - if (serverInfo.version === undefined) { - this.autoBatchTracing = false; - for (const preparedCreateParam of rawBatch.post) { - await this.createRun(preparedCreateParam as CreateRunParams); - } - for (const preparedUpdateParam of rawBatch.patch) { - if (preparedUpdateParam.id !== undefined) { - await this.updateRun( - preparedUpdateParam.id, - preparedUpdateParam as UpdateRunParams - ); - } - } - return; - } const batchChunks = { post: [] as (typeof rawBatch)["post"], patch: [] as (typeof rawBatch)["patch"], diff --git a/js/src/tests/batch_client.test.ts b/js/src/tests/batch_client.test.ts index 43c85c15d..f81d24bfa 100644 --- a/js/src/tests/batch_client.test.ts +++ b/js/src/tests/batch_client.test.ts @@ -753,19 +753,19 @@ describe.each(ENDPOINT_TYPES)( }); }); - it("If batching is unsupported, fall back to old endpoint", async () => { + it("Use batch endpoint if info call fails", async () => { const client = new Client({ apiKey: "test-api-key", autoBatchTracing: true, }); const callSpy = jest - .spyOn((client as any).caller, "call") + .spyOn((client as any).batchIngestCaller, "call") .mockResolvedValue({ ok: true, text: () => "", }); jest.spyOn(client as any, "_getServerInfo").mockImplementation(() => { - return {}; + throw new Error("Totally expected mock error"); }); const projectName = "__test_batch"; @@ -784,26 +784,32 @@ describe.each(ENDPOINT_TYPES)( dotted_order: dottedOrder, }); - await new Promise((resolve) => setTimeout(resolve, 300)); + await client.awaitPendingTraceBatches(); const calledRequestParam: any = callSpy.mock.calls[0][2]; + expect( await parseMockRequestBody(calledRequestParam?.body) ).toMatchObject({ - id: runId, - session_name: projectName, - extra: expect.anything(), - start_time: expect.any(Number), - name: "test_run", - run_type: "llm", - inputs: { text: "hello world" }, - trace_id: runId, - dotted_order: dottedOrder, + post: [ + { + id: runId, + session_name: projectName, + extra: expect.anything(), + start_time: expect.any(Number), + name: "test_run", + run_type: "llm", + inputs: { text: "hello world" }, + trace_id: runId, + dotted_order: dottedOrder, + }, + ], + patch: [], }); expect(callSpy).toHaveBeenCalledWith( _getFetchImplementation(), - "https://api.smith.langchain.com/runs", + "https://api.smith.langchain.com/runs/batch", expect.objectContaining({ body: expect.any(String), })