Skip to main content

Prisma

For augmenting existing models in PostgreSQL database with vector search, Langchain supports using Prisma together with PostgreSQL and pgvector Postgres extension.

Setup

Setup database instance with Supabase

Refer to the Prisma and Supabase integration guide to setup a new database instance with Supabase and Prisma.

Install Prisma

npm install prisma

Setup pgvector self hosted instance with docker-compose

pgvector provides a prebuilt Docker image that can be used to quickly setup a self-hosted Postgres instance.

services:
db:
image: ankane/pgvector
ports:
- 5432:5432
volumes:
- db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=
- POSTGRES_USER=
- POSTGRES_DB=

volumes:
db:

Create a new schema

Assuming you haven't created a schema yet, create a new model with a vector field of type Unsupported("vector"):

model Document {
id String @id @default(cuid())
content String
vector Unsupported("vector")?
}

Afterwards, create a new migration with --create-only to avoid running the migration directly.

npx prisma migrate dev --create-only

Add the following line to the newly created migration to enable pgvector extension if it hasn't been enabled yet:

CREATE EXTENSION IF NOT EXISTS vector;

Run the migration afterwards:

npx prisma migrate dev

Usage

npm install @langchain/openai @langchain/community
danger

Table names and column names (in fields such as tableName, vectorColumnName, columns and filter) are passed into SQL queries directly without parametrisation. These fields must be sanitized beforehand to avoid SQL injection.

import { PrismaVectorStore } from "@langchain/community/vectorstores/prisma";
import { OpenAIEmbeddings } from "@langchain/openai";
import { PrismaClient, Prisma, Document } from "@prisma/client";

export const run = async () => {
const db = new PrismaClient();

// Use the `withModel` method to get proper type hints for `metadata` field:
const vectorStore = PrismaVectorStore.withModel<Document>(db).create(
new OpenAIEmbeddings(),
{
prisma: Prisma,
tableName: "Document",
vectorColumnName: "vector",
columns: {
id: PrismaVectorStore.IdColumn,
content: PrismaVectorStore.ContentColumn,
},
}
);

const texts = ["Hello world", "Bye bye", "What's this?"];
await vectorStore.addModels(
await db.$transaction(
texts.map((content) => db.document.create({ data: { content } }))
)
);

const resultOne = await vectorStore.similaritySearch("Hello world", 1);
console.log(resultOne);

// create an instance with default filter
const vectorStore2 = PrismaVectorStore.withModel<Document>(db).create(
new OpenAIEmbeddings(),
{
prisma: Prisma,
tableName: "Document",
vectorColumnName: "vector",
columns: {
id: PrismaVectorStore.IdColumn,
content: PrismaVectorStore.ContentColumn,
},
filter: {
content: {
equals: "default",
},
},
}
);

await vectorStore2.addModels(
await db.$transaction(
texts.map((content) => db.document.create({ data: { content } }))
)
);

// Use the default filter a.k.a {"content": "default"}
const resultTwo = await vectorStore.similaritySearch("Hello world", 1);
console.log(resultTwo);
};

API Reference:

The following SQL operators are available as filters: equals, in, isNull, isNotNull, like, lt, lte, gt, gte, not.

The samples above uses the following schema:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model Document {
id String @id @default(cuid())
content String
namespace String? @default("default")
vector Unsupported("vector")?
}

API Reference:

    You can remove namespace if you don't need it.


    Help us out by providing feedback on this documentation page: