Skip to content

Commit

Permalink
fix(js): Removes langchain and @langchain/core from peer deps to fix …
Browse files Browse the repository at this point in the history
…npm installation (#1005)

npm seems to have changed the way they handle circular deps - folks
installing even old versions of `@langchain/core` that rely on a
LangSmith version with the circular peer dep with npm are now getting:

```
Jacob:foo jacoblee$ npm i @langchain/core@0.1.29
npm ERR! Cannot read properties of null (reading 'edgesOut')
```

This works:

```
{
  "name": "foo",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@langchain/core": "^0.1.29"
  },
  "overrides": {
    "langsmith": "0.1.18"
  }
}
```

This doesn't:

```
{
  "name": "foo",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@langchain/core": "^0.1.29"
  },
  "overrides": {
    "langsmith": "0.1.55"
  }
}
```

@dqbd I think this will break bundlers so we shouldn't merge but maybe
we can otherwise mark as external? Otherwise we will have to split out
all non-LangChain related code into e.g. `@langchain/langsmith-core`,
have `@langchain/core` depend on that, and have `langsmith` re-export
all of `@langchain/langsmith-core` with extra entrypoints, which is not
ideal.
  • Loading branch information
jacoblee93 committed Sep 16, 2024
1 parent 5ed1a6f commit e32c3c1
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 143 deletions.
18 changes: 5 additions & 13 deletions js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "langsmith",
"version": "0.1.55",
"version": "0.1.56",
"description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
"packageManager": "yarn@1.22.19",
"files": [
Expand Down Expand Up @@ -109,9 +109,9 @@
"@babel/preset-env": "^7.22.4",
"@faker-js/faker": "^8.4.1",
"@jest/globals": "^29.5.0",
"@langchain/core": "^0.2.17",
"@langchain/langgraph": "^0.0.29",
"@langchain/openai": "^0.2.5",
"@langchain/core": "^0.3.1",
"@langchain/langgraph": "^0.2.3",
"@langchain/openai": "^0.3.0",
"@tsconfig/recommended": "^1.0.2",
"@types/jest": "^29.5.1",
"@typescript-eslint/eslint-plugin": "^5.59.8",
Expand All @@ -126,7 +126,7 @@
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"langchain": "^0.2.10",
"langchain": "^0.3.2",
"openai": "^4.38.5",
"prettier": "^2.8.8",
"ts-jest": "^29.1.0",
Expand All @@ -135,19 +135,11 @@
"zod": "^3.23.8"
},
"peerDependencies": {
"@langchain/core": "*",
"langchain": "*",
"openai": "*"
},
"peerDependenciesMeta": {
"openai": {
"optional": true
},
"langchain": {
"optional": true
},
"@langchain/core": {
"optional": true
}
},
"lint-staged": {
Expand Down
2 changes: 0 additions & 2 deletions js/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3517,11 +3517,9 @@ export class Client {
}

/**
*
* This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
* Using this method directly returns the JSON string of the prompt rather than a LangChain object.
* @private
*
*/
public async _pullPrompt(
promptIdentifier: string,
Expand Down
17 changes: 14 additions & 3 deletions js/src/evaluation/_runner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Client, RunTree, RunTreeConfig } from "../index.js";
import { getLangchainCallbacks } from "../langchain.js";
import { BaseRun, Example, KVMap, Run, TracerSession } from "../schemas.js";
import { traceable } from "../traceable.js";
import { getDefaultRevisionId, getGitInfo } from "../utils/_git.js";
Expand Down Expand Up @@ -882,8 +881,20 @@ async function _forward(
const wrappedFn =
"invoke" in fn
? traceable(async (inputs) => {
const callbacks = await getLangchainCallbacks();
return fn.invoke(inputs, { callbacks });
let langChainCallbacks;
try {
// TODO: Deprecate this and rely on interop on 0.2 minor bump.
const { getLangchainCallbacks } = await import("../langchain.js");
langChainCallbacks = await getLangchainCallbacks();
} catch {
// no-op
}
// Issue with retrieving LangChain callbacks, rely on interop
if (langChainCallbacks === undefined) {
return await fn.invoke(inputs);
} else {
return await fn.invoke(inputs, { callbacks: langChainCallbacks });
}
}, options)
: traceable(fn, options);

Expand Down
5 changes: 4 additions & 1 deletion js/src/evaluation/langchain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Run, Example } from "../schemas.js";
// eslint-disable-next-line import/no-extraneous-dependencies
import { type LoadEvaluatorOptions, loadEvaluator } from "langchain/evaluation";
import type { Run, Example } from "../schemas.js";
import { getLangchainCallbacks } from "../langchain.js";

function isStringifiable(
Expand Down Expand Up @@ -27,6 +28,8 @@ function getPrimitiveValue(value: unknown) {
}

/**
* @deprecated Use `evaluate` instead.
*
* This utility function loads a LangChain string evaluator and returns a function
* which can be used by newer `evaluate` function.
*
Expand Down
2 changes: 1 addition & 1 deletion js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export { RunTree, type RunTreeConfig } from "./run_trees.js";
export { overrideFetchImplementation } from "./singletons/fetch.js";

// Update using yarn bump-version
export const __version__ = "0.1.55";
export const __version__ = "0.1.56";
5 changes: 5 additions & 0 deletions js/src/langchain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// These `@langchain/core` imports are intentionally not peer dependencies
// to avoid package manager issues around circular dependencies.
// eslint-disable-next-line import/no-extraneous-dependencies
import { CallbackManager } from "@langchain/core/callbacks/manager";
// eslint-disable-next-line import/no-extraneous-dependencies
import { LangChainTracer } from "@langchain/core/tracers/tracer_langchain";
// eslint-disable-next-line import/no-extraneous-dependencies
import {
Runnable,
RunnableConfig,
Expand Down
2 changes: 1 addition & 1 deletion js/src/tests/run_trees.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test("Should work with manually set API key", async () => {
project_name: projectName,
});
await runTree.postRun();
await new Promise((resolve) => setTimeout(resolve, 1000));
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(callSpy).toHaveBeenCalled();
} finally {
process.env.LANGCHAIN_API_KEY = key;
Expand Down
1 change: 1 addition & 0 deletions js/src/tests/traceable_langchain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ describe("to langchain", () => {

const result = await main({ texts: ["Hello world", "Who are you?"] });

await awaitAllCallbacks();
expect(result).toEqual(["Hello world", "Who are you?"]);
expect(getAssumedTreeFromCalls(callSpy.mock.calls)).toMatchObject({
nodes: [
Expand Down
3 changes: 2 additions & 1 deletion js/src/tests/utils/mock_client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { jest } from "@jest/globals";
import { Client } from "../../index.js";
// eslint-disable-next-line import/no-extraneous-dependencies
import { LangChainTracer } from "@langchain/core/tracers/tracer_langchain";
import { Client } from "../../index.js";

type ClientParams = Exclude<ConstructorParameters<typeof Client>[0], undefined>;
export const mockClient = (config?: Omit<ClientParams, "autoBatchTracing">) => {
Expand Down
Loading

0 comments on commit e32c3c1

Please sign in to comment.