Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9dfff08
standard-tests[major]: Init package
bracesproul May 30, 2024
1b3a79b
fix build, cleanup
bracesproul May 30, 2024
968a047
base class and unit tests
bracesproul May 31, 2024
6b1c916
format n lint
bracesproul May 31, 2024
359ef3e
updates
bracesproul May 31, 2024
ebca98a
Added standard unit tests to oai and scripts, made getLsParams public
bracesproul May 31, 2024
075ac8a
yarn install
bracesproul May 31, 2024
c292da5
always include api key
bracesproul May 31, 2024
832c015
set env var instead of constructor args
bracesproul May 31, 2024
9d87163
added integration tests
bracesproul May 31, 2024
b36427b
add int tests to openai
bracesproul May 31, 2024
1967eb9
add wso tests
bracesproul May 31, 2024
c6addda
Add to root & turbo, added gh action
bracesproul May 31, 2024
40b8109
Merge branch 'main' into brace/standard-tests
bracesproul May 31, 2024
16feca5
usage metadata tests for streaming and invoke
bracesproul May 31, 2024
16400e4
Added call options arg to integration tests
bracesproul May 31, 2024
7e566a7
tmp run standard test action in pr ci
bracesproul May 31, 2024
d9ec190
remove from pr ci
bracesproul May 31, 2024
fbb379a
test moar things, add readme
bracesproul Jun 1, 2024
dbed9df
chore: lint files
bracesproul Jun 1, 2024
0cc5eff
Merge branch 'main' of https://github.com/langchain-ai/langchainjs in…
bracesproul Jun 1, 2024
b91d7fb
Merge branch 'main' of https://github.com/langchain-ai/langchainjs in…
bracesproul Jun 2, 2024
8489cd4
token usage standard tests non streaming
bracesproul Jun 2, 2024
6e53484
Merge branch 'main' into brace/standard-tests
bracesproul Jun 4, 2024
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
base class and unit tests
  • Loading branch information
bracesproul committed May 31, 2024
commit 968a0470c5946fa58837bdad26ca364f4f973a8d
3 changes: 2 additions & 1 deletion libs/langchain-standard-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"author": "LangChain",
"license": "MIT",
"dependencies": {
"@langchain/core": "workspace:*"
"@langchain/core": "workspace:*",
"zod": "^3.22.4"
},
"devDependencies": {
"@jest/globals": "^29.5.0",
Expand Down
31 changes: 31 additions & 0 deletions libs/langchain-standard-tests/src/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
BaseChatModel,
BaseChatModelCallOptions,
} from "@langchain/core/language_models/chat_models";
import { BaseMessageChunk } from "@langchain/core/messages";

export type BaseChatModelConstructor<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> = new (...args: any[]) => BaseChatModel<CallOptions, OutputMessageType>;

export type BaseChatModelsTestsFields<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> = {
cls: BaseChatModelConstructor<CallOptions, OutputMessageType>;
};

export class BaseChatModelsTests<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> implements BaseChatModelsTestsFields<CallOptions, OutputMessageType>
{
cls: BaseChatModelConstructor<CallOptions, OutputMessageType>;

constructor(
fields: BaseChatModelsTestsFields<CallOptions, OutputMessageType>
) {
this.cls = fields.cls;
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
export {};
import {
BaseChatModel,
BaseChatModelCallOptions,
} from "@langchain/core/language_models/chat_models";
import { BaseMessageChunk } from "@langchain/core/messages";

type BaseChatModelConstructor<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> = new (...args: any[]) => BaseChatModel<CallOptions, OutputMessageType>;

export class ChatModelsIntegrationTests<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> {
cls: BaseChatModel<CallOptions, OutputMessageType>;

constructor(cls: BaseChatModelConstructor<CallOptions, OutputMessageType>) {
this.cls = new cls();
}
}
191 changes: 190 additions & 1 deletion libs/langchain-standard-tests/src/unit_tests/chat_models.ts
Original file line number Diff line number Diff line change
@@ -1 +1,190 @@
export {};
import { expect } from "@jest/globals";
import { BaseChatModelsTests, BaseChatModelsTestsFields } from "../base.js";
import {
BaseChatModelCallOptions,
LangSmithParams,
} from "@langchain/core/language_models/chat_models";
import { BaseMessage, BaseMessageChunk } from "@langchain/core/messages";
import { z } from "zod";
import { StructuredTool } from "@langchain/core/tools";
import { ChatResult } from "@langchain/core/outputs";
import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";

const person = z
.object({
name: z.string().describe("Name of the person"),
age: z.number().int().positive().describe("Age of the person"),
})
.describe("A person");

class PersonTool extends StructuredTool {
name = "PersonTool";

description = person.description ?? "description";

schema = person;

async _call(input: z.infer<typeof person>) {
return JSON.stringify(input);
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type RecordStringAny = Record<string, any>;

export class ChatModelUnitTests<
CallOptions extends BaseChatModelCallOptions = BaseChatModelCallOptions,
OutputMessageType extends BaseMessageChunk = BaseMessageChunk
> extends BaseChatModelsTests<CallOptions, OutputMessageType> {
constructor(
fields: BaseChatModelsTestsFields<CallOptions, OutputMessageType>
) {
super(fields);
}

testChatModelInit(constructorArgs: RecordStringAny) {
const chatModel = new this.cls(constructorArgs);
expect(chatModel).toBeDefined();
}

testChatModelInitApiKey(constructorArgs: RecordStringAny) {
const params = { ...constructorArgs, apiKey: "test" };
const chatModel = new this.cls(params);
expect(chatModel).toBeDefined();
}

testChatModelInitStreaming(constructorArgs: RecordStringAny) {
const params = { ...constructorArgs, streaming: true };
const chatModel = new this.cls(params);
expect(chatModel).toBeDefined();
}

testChatModelWithBindTools(
constructorArgs: RecordStringAny,
chatModelHasToolCalling: boolean
) {
if (!chatModelHasToolCalling) {
return;
}
const chatModel = new this.cls(constructorArgs);
expect(chatModel.bindTools?.([new PersonTool()])).toBeDefined();
}

testChatModelWithStructuredOutput(
constructorArgs: RecordStringAny,
chatModelHasStructuredOutput: boolean
) {
if (!chatModelHasStructuredOutput) {
return;
}
const chatModel = new this.cls(constructorArgs);
expect((chatModel as any).withStructuredOutput?.(person)).toBeDefined();
}

testStandardParams(constructorArgs: RecordStringAny) {
const expectedParams: LangSmithParams = {
ls_provider: "string",
ls_model_name: "string",
ls_model_type: "chat",
ls_temperature: 0,
ls_max_tokens: 0,
ls_stop: ["Array<string>"],
};
class ModelExtendsChatModel extends this.cls {
constructor(fields: RecordStringAny) {
super(fields);
}

_llmType(): string {
throw new Error("Method not implemented.");
}

_generate(
_messages: BaseMessage[],
_options: this["ParsedCallOptions"],
_runManager?: CallbackManagerForLLMRun | undefined
): Promise<ChatResult> {
throw new Error("Method not implemented.");
}

checkLsParams(options: this["ParsedCallOptions"]) {
const lsParams = this.getLsParams(options);
return lsParams;
}
}
const extendedModel = new ModelExtendsChatModel(constructorArgs);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const lsParams = extendedModel.checkLsParams({} as any);
expect(lsParams).toBeDefined();
expect(Object.keys(lsParams).sort()).toEqual(
Object.keys(expectedParams).sort()
);
}

/**
* Run all unit tests for the chat model.
* Each test is wrapped in a try/catch block to prevent the entire test suite from failing.
* If a test fails, the error is logged to the console, and the test suite continues.
* @param {RecordStringAny} constructorArgs The arguments to pass to the chat model constructor.
* @param {boolean} chatModelHasToolCalling Whether the chat model has a tool calling method.
* @param {boolean} chatModelHasStructuredOutput Whether the chat model has a structured output method.
* @returns {void}
*/
runTests(
constructorArgs: RecordStringAny,
chatModelHasToolCalling: boolean,
chatModelHasStructuredOutput: boolean
) {
try {
this.testChatModelInit(constructorArgs);
} catch (e) {
console.error("'testChatModelInit' FAILED\n");
console.error(e);
console.error("\n");
}

try {
this.testChatModelInitApiKey(constructorArgs);
} catch (e) {
console.error("'testChatModelInitApiKey' FAILED\n");
console.error(e);
console.error("\n");
}

try {
this.testChatModelInitStreaming(constructorArgs);
} catch (e) {
console.error("'testChatModelInitStreaming' FAILED\n");
console.error(e);
console.error("\n");
}

try {
this.testChatModelWithBindTools(constructorArgs, chatModelHasToolCalling);
} catch (e) {
console.error("'testChatModelWithBindTools' FAILED\n");
console.error(e);
console.error("\n");
}

try {
this.testChatModelWithStructuredOutput(
constructorArgs,
chatModelHasStructuredOutput
);
} catch (e) {
console.error("'testChatModelWithStructuredOutput' FAILED\n");
console.error(e);
console.error("\n");
}

try {
this.testStandardParams(constructorArgs);
} catch (e) {
console.error("'testStandardParams' FAILED\n");
console.error(e);
console.error("\n");
}
}
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10215,6 +10215,7 @@ __metadata:
rollup: ^4.5.2
ts-jest: ^29.1.0
typescript: ^5.4.5
zod: ^3.22.4
languageName: unknown
linkType: soft

Expand Down