mirror of
https://github.com/labring/FastGPT.git
synced 2026-02-27 01:02:22 +08:00
* feat(vectordb): add OceanBase HNSW quantization (HNSW_SQ/HNSW_BQ) (#6348) Support OceanBase vector index quantization via VECTOR_VQ_LEVEL: - 32 (default): hnsw + inner_product - 8: hnsw_sq + inner_product (2-3x memory savings) - 1: hnsw_bq + cosine (~15x memory savings) HNSW_BQ requires cosine distance per OceanBase docs. Tested on OceanBase 4.3.5.5 (BP5). Closes #6202 * feat: add test inclusion for vectorDB tests in vitest configuration (#6358) * feat: add test inclusion for vectorDB tests in vitest configuration * refactor: update vectorDB README and setup for environment configuration - Enhanced README to clarify the use of factory pattern for vectorDB integration tests. - Updated instructions for setting up environment variables from a local file. - Removed obsolete PG integration test file and adjusted test execution instructions. - Improved structure explanation for shared test data and factory functions. * perf: integrationTest * feat: vector integration --------- Co-authored-by: ZHANG Yixin <hi.yixinz@gmail.com> Co-authored-by: Jingchao <alswlx@gmail.com>
160 lines
4.9 KiB
TypeScript
160 lines
4.9 KiB
TypeScript
import { beforeAll, describe, expect, test } from 'vitest';
|
|
import type { VectorControllerType } from '@fastgpt/service/common/vectorDB/type';
|
|
import { createTestIds, QUERY_VECTOR, TEST_COLLECTION_IDS, TEST_VECTORS } from './testData';
|
|
|
|
const insertTestVectors = async (
|
|
vectorCtrl: VectorControllerType,
|
|
teamId: string,
|
|
datasetId: string
|
|
) => {
|
|
const insertIds: string[] = [];
|
|
|
|
await Promise.all(
|
|
TEST_VECTORS.map(async (vector, index) => {
|
|
const { insertIds: ids } = await vectorCtrl.insert({
|
|
teamId,
|
|
datasetId,
|
|
collectionId: TEST_COLLECTION_IDS[index],
|
|
vectors: [vector]
|
|
});
|
|
insertIds.push(ids[0]);
|
|
})
|
|
);
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
return insertIds;
|
|
};
|
|
|
|
const cleanupTestVectors = async (
|
|
vectorCtrl: VectorControllerType,
|
|
teamId: string,
|
|
datasetId: string
|
|
) => {
|
|
try {
|
|
await vectorCtrl.delete({
|
|
teamId,
|
|
datasetIds: [datasetId]
|
|
});
|
|
} catch (error) {
|
|
// Ignore cleanup errors
|
|
}
|
|
};
|
|
|
|
export const createVectorDBTestSuite = (vectorCtrl: VectorControllerType) => {
|
|
describe.sequential('vectorDB integration', () => {
|
|
beforeAll(async () => {
|
|
await vectorCtrl.init();
|
|
});
|
|
|
|
test('insert and count', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
const insertIds = await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
expect(insertIds).toHaveLength(TEST_VECTORS.length);
|
|
|
|
const count = await vectorCtrl.getVectorCount({ teamId, datasetId });
|
|
expect(count).toBe(TEST_VECTORS.length);
|
|
|
|
const collectionCount = await vectorCtrl.getVectorCount({
|
|
teamId,
|
|
datasetId,
|
|
collectionId: TEST_COLLECTION_IDS[0]
|
|
});
|
|
expect(collectionCount).toBe(1);
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
|
|
test('embRecall returns results', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
const { results } = await vectorCtrl.embRecall({
|
|
teamId,
|
|
datasetIds: [datasetId],
|
|
vector: QUERY_VECTOR,
|
|
limit: 3,
|
|
forbidCollectionIdList: []
|
|
});
|
|
|
|
expect(results.length).toBeGreaterThan(0);
|
|
expect(results.every((item) => TEST_COLLECTION_IDS.includes(item.collectionId))).toBe(true);
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
|
|
test('embRecall respects forbidCollectionIdList', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
const { results } = await vectorCtrl.embRecall({
|
|
teamId,
|
|
datasetIds: [datasetId],
|
|
vector: QUERY_VECTOR,
|
|
limit: 10,
|
|
forbidCollectionIdList: [TEST_COLLECTION_IDS[0]]
|
|
});
|
|
|
|
expect(results.length).toBeGreaterThan(0);
|
|
expect(results.every((item) => item.collectionId !== TEST_COLLECTION_IDS[0])).toBe(true);
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
|
|
test('embRecall respects filterCollectionIdList', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
const { results } = await vectorCtrl.embRecall({
|
|
teamId,
|
|
datasetIds: [datasetId],
|
|
vector: QUERY_VECTOR,
|
|
limit: 10,
|
|
forbidCollectionIdList: [],
|
|
filterCollectionIdList: [TEST_COLLECTION_IDS[1]]
|
|
});
|
|
|
|
expect(results.length).toBeGreaterThan(0);
|
|
expect(results.every((item) => item.collectionId === TEST_COLLECTION_IDS[1])).toBe(true);
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
|
|
test('getVectorDataByTime returns data', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
const insertIds = await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
const start = new Date(0);
|
|
const end = new Date(Date.now() + 600_000);
|
|
|
|
const data = await vectorCtrl.getVectorDataByTime(start, end);
|
|
const matchedIds = data
|
|
.filter((item) => item.teamId === teamId && item.datasetId === datasetId)
|
|
.map((item) => item.id);
|
|
|
|
expect(matchedIds.length).toBeGreaterThan(0);
|
|
expect(matchedIds).toEqual(expect.arrayContaining(insertIds));
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
|
|
test('delete by idList removes vectors', async () => {
|
|
const { teamId, datasetId } = createTestIds();
|
|
const insertIds = await insertTestVectors(vectorCtrl, teamId, datasetId);
|
|
|
|
await vectorCtrl.delete({
|
|
teamId,
|
|
idList: insertIds.slice(0, 2)
|
|
});
|
|
|
|
const count = await vectorCtrl.getVectorCount({ teamId, datasetId });
|
|
expect(count).toBe(TEST_VECTORS.length - 2);
|
|
|
|
await cleanupTestVectors(vectorCtrl, teamId, datasetId);
|
|
});
|
|
});
|
|
};
|