Skip to content

Commit 0fd9b54

Browse files
authored
test: Updated langchain vectorstore tests to use a custom vectorstore to simplify the testing process (#3793)
1 parent e02ce99 commit 0fd9b54

File tree

5 files changed

+72
-61
lines changed

5 files changed

+72
-61
lines changed

test/versioned/langchain-aws/package.json

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"targets": [
44
{
55
"name": "@langchain/aws",
6-
"minSupported": "1.0.0",
6+
"minSupported": "0.1.3",
77
"minAgentVersion": "13.8.0"
88
}
99
],
@@ -22,21 +22,7 @@
2222
},
2323
"files": [
2424
"runnables.test.js",
25-
"runnables-streaming.test.js"
26-
]
27-
},
28-
{
29-
"engines": {
30-
"node": ">=20"
31-
},
32-
"comment": "because @langchain/core and @langchain/community need to be the same minor version because of peer deps, we have to test with latest",
33-
"dependencies": {
34-
"@langchain/aws": "latest",
35-
"@langchain/core": "latest",
36-
"@langchain/community": "latest",
37-
"@elastic/elasticsearch": "8.13.1"
38-
},
39-
"files": [
25+
"runnables-streaming.test.js",
4026
"vectorstore.test.js"
4127
]
4228
}

test/versioned/langchain-aws/vectorstore.test.js

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const { removeModules } = require('../../lib/cache-buster')
1111
const { runVectorstoreTests } = require('../langchain/vectorstore')
1212
const { Document } = require('@langchain/core/documents')
1313
const { FAKE_CREDENTIALS, getAiResponseServer } = require('../../lib/aws-server-stubs')
14-
const params = require('../../lib/params')
1514
const helper = require('../../lib/agent_helper')
1615

1716
const config = {
@@ -27,19 +26,14 @@ test.beforeEach(async (ctx) => {
2726
ctx.nr.server = server
2827
ctx.nr.agent = helper.instrumentMockedAgent(config)
2928

29+
const { VectorStore } = require('@langchain/core/vectorstores')
30+
// must pass in VectorStore to ensure it's the same version as the test
31+
// and not whatever is installed in `test/versioned/langchain/`
32+
const CustomVectorStore = require('../langchain/custom-vector-store')(VectorStore)
3033
const { BedrockEmbeddings } = require('@langchain/aws')
3134
const { BedrockRuntimeClient } = require('@aws-sdk/client-bedrock-runtime')
3235
ctx.nr.langchainCoreVersion = require('@langchain/core/package.json').version
3336

34-
const { Client } = require('@elastic/elasticsearch')
35-
const clientArgs = {
36-
client: new Client({
37-
node: `http://${params.elastic_host}:${params.elastic_port}`
38-
}),
39-
indexName: 'test_langchain_aws_vectorstore'
40-
}
41-
const { ElasticVectorSearch } = require('@langchain/community/vectorstores/elasticsearch')
42-
4337
// Create the BedrockRuntimeClient with our mock endpoint
4438
const bedrockClient = new BedrockRuntimeClient({
4539
region: 'us-east-1',
@@ -60,18 +54,16 @@ test.beforeEach(async (ctx) => {
6054
pageContent: 'embed text amazon token count callback response'
6155
})
6256
]
63-
const vectorStore = new ElasticVectorSearch(ctx.nr.embedding, clientArgs)
64-
await vectorStore.deleteIfExists()
57+
const vectorStore = new CustomVectorStore(ctx.nr.embedding)
6558
await vectorStore.addDocuments(docs)
6659
ctx.nr.vs = vectorStore
6760
})
6861

6962
test.afterEach(async (ctx) => {
70-
await ctx.nr?.vs?.deleteIfExists()
7163
ctx.nr?.server?.destroy()
7264
helper.unloadAgent(ctx.nr.agent)
7365
// bust the require-cache so it can re-instrument
74-
removeModules(['@langchain/core', '@langchain/aws', '@aws-sdk', '@elastic', '@langchain/community'])
66+
removeModules(['@langchain/core', '@aws-sdk'])
7567
})
7668

7769
runVectorstoreTests({

test/versioned/langchain-openai/package.json

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"targets": [
44
{
55
"name": "@langchain/openai",
6-
"minSupported": "1.0.0",
6+
"minSupported": "0.2.0",
77
"minAgentVersion": "11.13.0"
88
}
99
],
@@ -22,23 +22,9 @@
2222
},
2323
"files": [
2424
"runnables.test.js",
25-
"runnables-streaming.test.js"
26-
]
27-
},
28-
{
29-
"engines": {
30-
"node": ">=20"
31-
},
32-
"comment": "because @langchain/core and @langchain/community need to be the same minor version because of peer deps, we have to test with latest",
33-
"dependencies": {
34-
"@langchain/core": "latest",
35-
"@langchain/community": "latest",
36-
"@langchain/openai": "latest",
37-
"@elastic/elasticsearch": "8.13.1"
38-
},
39-
"files": [
25+
"runnables-streaming.test.js",
4026
"vectorstore.test.js"
4127
]
4228
}
4329
]
44-
}
30+
}

test/versioned/langchain-openai/vectorstore.test.js

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const { removeModules } = require('../../lib/cache-buster')
1212
const { runVectorstoreTests } = require('../langchain/vectorstore')
1313
const { Document } = require('@langchain/core/documents')
1414
const createOpenAIMockServer = require('../openai/mock-server')
15-
const params = require('../../lib/params')
1615
const helper = require('../../lib/agent_helper')
1716

1817
const config = {
@@ -27,18 +26,13 @@ test.beforeEach(async (ctx) => {
2726
ctx.nr.server = server
2827
ctx.nr.agent = helper.instrumentMockedAgent(config)
2928

29+
const { VectorStore } = require('@langchain/core/vectorstores')
30+
// must pass in VectorStore to ensure it's the same version as the test
31+
// and not whatever is installed in `test/versioned/langchain/`
32+
const CustomVectorStore = require('../langchain/custom-vector-store')(VectorStore)
3033
const { OpenAIEmbeddings } = require('@langchain/openai')
3134
ctx.nr.langchainCoreVersion = require('@langchain/core/package.json').version
3235

33-
const { Client } = require('@elastic/elasticsearch')
34-
const clientArgs = {
35-
client: new Client({
36-
node: `http://${params.elastic_host}:${params.elastic_port}`
37-
}),
38-
indexName: 'test_langchain_openai_vectorstore'
39-
}
40-
const { ElasticVectorSearch } = require('@langchain/community/vectorstores/elasticsearch')
41-
4236
ctx.nr.embedding = new OpenAIEmbeddings({
4337
apiKey: 'fake-key',
4438
configuration: {
@@ -51,18 +45,16 @@ test.beforeEach(async (ctx) => {
5145
pageContent: 'This is an embedding test.'
5246
})
5347
]
54-
const vectorStore = new ElasticVectorSearch(ctx.nr.embedding, clientArgs)
55-
await vectorStore.deleteIfExists()
48+
const vectorStore = new CustomVectorStore(ctx.nr.embedding)
5649
await vectorStore.addDocuments(docs)
5750
ctx.nr.vs = vectorStore
5851
})
5952

6053
test.afterEach(async (ctx) => {
61-
await ctx.nr?.vs?.deleteIfExists()
6254
ctx.nr?.server?.close()
6355
helper.unloadAgent(ctx.nr.agent)
6456
// bust the require-cache so it can re-instrument
65-
removeModules(['@langchain/core', 'openai', '@elastic', '@langchain/community'])
57+
removeModules(['@langchain/core', 'openai'])
6658
})
6759

6860
runVectorstoreTests({
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2026 New Relic Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
'use strict'
7+
8+
/**
9+
* This is a function because we must pass in the appropriate `VectorStore` class
10+
* from either `langchain-openai` or `langchain-aws`.
11+
*
12+
* @param {VectorStore} VectorStore class from `@langchain/core/vectorstore`
13+
* @returns {object} CustomVectorStore to be used for testing
14+
*/
15+
module.exports = function createCustomVectorStore(VectorStore) {
16+
class CustomVectorStore extends VectorStore {
17+
/**
18+
* @param {object} embeddings Embedding function or object (required by VectorStore)
19+
* @param {object} [options] Optional config
20+
*/
21+
constructor(embeddings, options = {}) {
22+
super(embeddings, options)
23+
this._documents = []
24+
}
25+
26+
_vectorstoreType() {
27+
return 'custom'
28+
}
29+
30+
/**
31+
* Add documents to the vectorstore without generating real embeddings.
32+
* @param {Array<{pageContent: string, metadata?: object}>} docs documents to add
33+
*/
34+
async addDocuments(docs) {
35+
this._documents.push(...docs)
36+
}
37+
38+
/**
39+
* Perform an in-memory similarity search over stored documents.
40+
* Called by the base class `similaritySearch` after embedding the query.
41+
* @param {number[]} _vector unused vector prop
42+
* @param {number} k score
43+
* @param {object} [filter] filter query
44+
* @returns {Array} results from query
45+
*/
46+
async similaritySearchVectorWithScore(_vector, k, filter) {
47+
let docs = this._documents
48+
if (filter) {
49+
docs = docs.filter((doc) => Object.entries(filter).every(([key, value]) => doc.metadata?.[key] === value))
50+
}
51+
return docs.slice(0, k).map((doc) => [doc, 1.0])
52+
}
53+
}
54+
return CustomVectorStore
55+
}

0 commit comments

Comments
 (0)