Description
Checked other resources
- I added a very descriptive title to this issue.
- I searched the LangChain.js documentation with the integrated search.
- I used the GitHub search to find a similar question and didn't find it.
- I am sure that this is a bug in LangChain.js rather than my code.
- The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
Example Code
The following code:
// tests/dynamo-history.integration.test.ts // Renamed to indicate integration test
import {afterEach, beforeEach, describe, expect, it} from '@jest/globals';
import {AIMessage, BaseMessage, HumanMessage} from "@langchain/core/messages";
import {v4 as uuidv4} from "uuid";
// AWS SDK v3 imports for direct interaction in tests
import {DynamoDBClient} from "@aws-sdk/client-dynamodb";
import {DeleteCommand, DynamoDBDocumentClient, GetCommand} from "@aws-sdk/lib-dynamodb";
import {DynamoDBChatMessageHistory} from '@langchain/community/stores/message/dynamodb';
// --- Configuration ---
// Ensure these environment variables are set correctly for your test table/region
const TEST_TABLE_NAME = "TEST_TABLE"; // Use a dedicated test table name
const TEST_REGION = process.env.AWS_REGION || "us-east-1";
if (!process.env.DYNAMODB_HISTORY_TABLE_TEST) {
console.warn(`TEST_TABLE env var not set. Using default: ${TEST_TABLE_NAME}. Ensure this table exists.`);
}
// --- Real AWS SDK Client for Test Setup/Verification/Cleanup ---
// Uses default credential provider chain
const realDdbClient = new DynamoDBClient({ region: TEST_REGION });
const realDocClient = DynamoDBDocumentClient.from(realDdbClient);
// Helper to create history instance pointing to the real table
const createHistory = (sessionId: string) => {
return new DynamoDBChatMessageHistory({
tableName: TEST_TABLE_NAME,
sessionId: sessionId,
partitionKey: 'pk',
sortKey: 'sk',
// Config for the *internal* client used by the history class
config: {
region: TEST_REGION,
},
});
};
// Define the sort key value the library likely uses or expects
// Adjust if needed based on library specifics or explicit configuration
const ACTUAL_SORT_KEY_VALUE = 'sk';
// Helper function to clean up item after test using the REAL client
const cleanupItem = async (sessionId: string) => {
try {
await realDocClient.send(new DeleteCommand({
TableName: TEST_TABLE_NAME,
Key: { pk: sessionId, sk: ACTUAL_SORT_KEY_VALUE },
}));
// console.log(`Cleaned up item for sessionId: ${sessionId}`);
} catch (error) {
console.error(`Error cleaning up sessionId ${sessionId}:`, error);
// Don't fail test run due to cleanup error, but log it
}
};
// --- Test Suite ---
describe("DynamoDBChatMessageHistory Integration Test", () => {
let currentSessionId: string;
beforeEach(() => {
// Generate a unique sessionId for each test to ensure isolation
currentSessionId = uuidv4();
});
afterEach(async () => {
// Clean up the item created during the test
if (currentSessionId) {
await cleanupItem(currentSessionId);
}
});
it("should instantiate correctly (no AWS call)", () => {
const historyStore = createHistory(currentSessionId);
expect(historyStore).toBeInstanceOf(DynamoDBChatMessageHistory);
});
it("should get empty messages if no history exists in DB", async () => {
const historyStore = createHistory(currentSessionId);
// Ensure item doesn't exist (handled by afterEach generally)
const messages = await historyStore.getMessages();
expect(messages).toEqual([]);
});
it("should add messages and store them in DynamoDB", async () => {
const historyStore = createHistory(currentSessionId);
const messagesToAdd: BaseMessage[] = [
new HumanMessage({
content: [
{
type: "text",
text: `Hi! I'm human` // Uses domString variable
}
]
}),
new AIMessage("Hi there! I'm real!"),
];
// --- Act ---
await historyStore.addMessages(messagesToAdd);
// --- Assert ---
// Verify by fetching directly from DynamoDB
const { Item } = await realDocClient.send(new GetCommand({
TableName: TEST_TABLE_NAME,
Key: { pk: currentSessionId, sk: 'sk' },
}));
console.log(Item);
expect(Item).toBeDefined();
expect(Item?.pk).toBe(currentSessionId);
expect(Item?.sk).toBe('sk');
expect(Item?.messages).toBeDefined();
});
});
Error Message and Stack Trace (if applicable)
Error: Error adding messages: UnknownError
at DynamoDBChatMessageHistory.addMessages (C:\Users\aaras\Dropbox\startup\website_augmenter\similar_extensions\utterXAmplifyBackend\node_modules\.pnpm\@[email protected]_c3b7e1eec298838f464006b49002acf9\node_modules\@langchain\community\dist\stores\message\dynamodb.cjs:210:19)
at processTicksAndRejections (node:internal/process/task_queues:105:5)
at Object.<anonymous> (C:\Users\aaras\Dropbox\startup\website_augmenter\similar_extensions\utterXAmplifyBackend\tests\dynamo-history-issue.test.ts:101:9)
Description
This works with HumanMessage("I'm human")
, the issue is serialization.
System Info
[email protected] | MIT | deps: 12 | versions: 316
Typescript bindings for langchain
https://github.com/langchain-ai/langchainjs/tree/main/langchain/
keywords: llm, ai, gpt3, chain, prompt, prompt engineering, chatgpt, machine learning, ml, openai, embeddings, vectorstores
dist
.tarball: https://registry.npmjs.org/langchain/-/langchain-0.3.21.tgz
.shasum: 5f41f9e11f7f087b1883cc579c2f8e11597d6e4f
.integrity: sha512-fpor/V/xJRoLM7s1yQGlUE6aZIe6LLm7ciZcstNbBUYdFpCSigvADsW2cqlBCdbMXJxb5I/z9jznjGnmciJ+aw==
.unpackedSize: 2.9 MB
dependencies:
@langchain/openai: >=0.1.0 <0.6.0 js-yaml: ^4.1.0 openapi-types: ^12.1.3 yaml: ^2.2.1
@langchain/textsplitters: >=0.0.0 <0.2.0 jsonpointer: ^5.0.1 p-retry: 4 zod-to-json-schema: ^3.22.3
js-tiktoken: ^1.0.12 langsmith: >=0.2.8 <0.4.0 uuid: ^10.0.0 zod: ^3.22.4
maintainers:
- nfcampos [email protected]
- jacoblee93 [email protected]
- andrewnguonly [email protected]
- benjamincburns [email protected]
- davidduong [email protected]
- hwchase17 [email protected]
- basproul [email protected]
dist-tags:
latest: 0.3.21 next: 0.3.2-rc.0 tag-for-publishing-older-releases: 0.2.20