Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

community[patch]: Adds support for passing schemaName to pgvector #4543

Merged
merged 20 commits into from
Feb 29, 2024
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions libs/langchain-community/src/vectorstores/pgvector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface PGVectorStoreArgs {
collectionTableName?: string;
collectionName?: string;
collectionMetadata?: Metadata | null;
schemaName?: string | null;
extensionSchemaName?: string | null;
columns?: {
idColumnName?: string;
vectorColumnName?: string;
Expand Down Expand Up @@ -51,12 +53,16 @@ export class PGVectorStore extends VectorStore {

collectionMetadata: Metadata | null;

schemaName: string | null;

idColumnName: string;

vectorColumnName: string;

contentColumnName: string;

extensionSchemaName: string | null;

metadataColumnName: string;

filter?: Metadata;
Expand All @@ -82,6 +88,9 @@ export class PGVectorStore extends VectorStore {
this.collectionTableName = config.collectionTableName;
this.collectionName = config.collectionName ?? "langchain";
this.collectionMetadata = config.collectionMetadata ?? null;
this.schemaName = config.schemaName ?? null;
this.extensionSchemaName = config.extensionSchemaName ?? null;

this.filter = config.filter;

this.vectorColumnName = config.columns?.vectorColumnName ?? "embedding";
Expand All @@ -98,6 +107,12 @@ export class PGVectorStore extends VectorStore {
!!config.verbose;
}

get computedTableName() {
return this.schemaName == null
? `${this.tableName}`
: `"${this.schemaName}"."${this.tableName}"`;
}

/**
* Static method to create a new `PGVectorStore` instance from a
* connection. It creates a table if one does not exist, and calls
Expand Down Expand Up @@ -238,7 +253,7 @@ export class PGVectorStore extends VectorStore {
.join(", ");

const text = `
INSERT INTO ${this.tableName}(
INSERT INTO ${this.computedTableName}(
${columns.map((column) => `"${column}"`).join(", ")}
)
VALUES ${valuesPlaceholders}
Expand Down Expand Up @@ -323,7 +338,7 @@ export class PGVectorStore extends VectorStore {
const params = collectionId ? [ids, collectionId] : [ids];

const queryString = `
DELETE FROM ${this.tableName}
DELETE FROM ${this.computedTableName}
WHERE ${collectionId ? "collection_id = $2 AND " : ""}${
this.idColumnName
} = ANY($1::uuid[])
Expand All @@ -348,7 +363,7 @@ export class PGVectorStore extends VectorStore {
const params = collectionId ? [filter, collectionId] : [filter];

const queryString = `
DELETE FROM ${this.tableName}
DELETE FROM ${this.computedTableName}
WHERE ${collectionId ? "collection_id = $2 AND " : ""}${
this.metadataColumnName
}::jsonb @> $1
Expand Down Expand Up @@ -454,9 +469,14 @@ export class PGVectorStore extends VectorStore {
? `WHERE ${whereClauses.join(" AND ")}`
: "";

const operatorString =
this.extensionSchemaName !== null
? `OPERATOR(${this.extensionSchemaName}.<=>)`
: "<=>";

const queryString = `
SELECT *, ${this.vectorColumnName} <=> $1 as "_distance"
FROM ${this.tableName}
SELECT *, "${this.vectorColumnName}" ${operatorString} $1 as "_distance"
FROM ${this.computedTableName}
${whereClause}
${collectionId ? "AND collection_id = $3" : ""}
ORDER BY "_distance" ASC
Expand Down Expand Up @@ -485,17 +505,29 @@ export class PGVectorStore extends VectorStore {
* @returns Promise that resolves when the table has been ensured.
*/
async ensureTableInDatabase(): Promise<void> {
await this.pool.query("CREATE EXTENSION IF NOT EXISTS vector;");
await this.pool.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";');

await this.pool.query(`
CREATE TABLE IF NOT EXISTS ${this.tableName} (
const vectorQuery =
this.extensionSchemaName == null
? "CREATE EXTENSION IF NOT EXISTS vector;"
: `CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA "${this.extensionSchemaName}";`;
const uuidQuery =
this.extensionSchemaName == null
? 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'
: `CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "${this.extensionSchemaName}";`;
const extensionName =
this.extensionSchemaName == null
? "vector"
: `"${this.extensionSchemaName}"."vector"`;
const tableQuery = `
CREATE TABLE IF NOT EXISTS ${this.computedTableName} (
"${this.idColumnName}" uuid NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY,
"${this.contentColumnName}" text,
"${this.metadataColumnName}" jsonb,
"${this.vectorColumnName}" vector
"${this.vectorColumnName}" ${extensionName}
);
`);
`;
await this.pool.query(vectorQuery);
await this.pool.query(uuidQuery);
await this.pool.query(tableQuery);
}

/**
Expand All @@ -506,22 +538,23 @@ export class PGVectorStore extends VectorStore {
*/
async ensureCollectionTableInDatabase(): Promise<void> {
try {
await this.pool.query(`
const queryString = `
CREATE TABLE IF NOT EXISTS ${this.collectionTableName} (
uuid uuid NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY,
name character varying,
cmetadata jsonb
);

ALTER TABLE ${this.tableName}
ALTER TABLE ${this.computedTableName}
ADD COLUMN collection_id uuid;

ALTER TABLE ${this.tableName}
ALTER TABLE ${this.computedTableName}
ADD CONSTRAINT ${this.tableName}_collection_id_fkey
FOREIGN KEY (collection_id)
REFERENCES ${this.collectionTableName}(uuid)
ON DELETE CASCADE;
`);
`;
await this.pool.query(queryString);
} catch (e) {
if (!(e as Error).message.includes("already exists")) {
console.error(e);
Expand Down
Loading