Skip to content

Commit

Permalink
Add implementation of Prisma vectorstore (#440)
Browse files Browse the repository at this point in the history
* Add implementation of Prisma vectorstore

* Fix CI

* FIx lint issues

* FIx incorrect index for addVectors

* Add example to Prisma

* Fix returned types

* Add docs

* Remove @prisma/client from peer-dependencies and dependencies

* Add implementation of fromTexts and fromDocuments

* Update yarn.lock

* Fix broken example
  • Loading branch information
dqbd authored Apr 8, 2023
1 parent 3f43d9b commit 5ce8f2b
Show file tree
Hide file tree
Showing 13 changed files with 526 additions and 8 deletions.
74 changes: 74 additions & 0 deletions docs/docs/modules/indexes/vector_stores/prisma.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Prisma

For augmenting existing models in PostgreSQL database with vector search, Langchain supports using [Prisma](https://www.prisma.io/) together with PostgreSQL and [`pgvector`](https://github.com/pgvector/pgvector) Postgres extension.

## Setup

### Setup database instance with Supabase

Refer to the [Prisma and Supabase integration guide](https://supabase.com/docs/guides/integrations/prisma) to setup a new database instance with Supabase and 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.

```yaml
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")`:

```prisma
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.

```bash npm2yarn
npm run 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:

```sql
CREATE EXTENSION IF NOT EXISTS vector;
```

Run the migration afterwards:

```bash npm2yarn
npm run prisma migrate dev
```

## Usage

import CodeBlock from "@theme/CodeBlock";
import Example from "@examples/indexes/vector_stores/prisma_vectorstore/prisma.ts";
import Schema from "@examples/indexes/vector_stores/prisma_vectorstore/prisma/schema.prisma";

Use the `withModel` method to get proper type hints for `metadata` field:

<CodeBlock language="typescript">{Example}</CodeBlock>

The sample above uses the following schema:

<CodeBlock language="prisma">{Schema}</CodeBlock>
3 changes: 3 additions & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"scripts": {
"build": "tsc --declaration --outDir dist/",
"start": "tsx -r dotenv/config src/index.ts",
"postinstall": "prisma generate --schema ./src/indexes/vector_stores/prisma_vectorstore/prisma/schema.prisma",
"start:dist": "yarn build && node -r dotenv/config dist/index.js",
"lint": "eslint src",
"lint:fix": "yarn lint --fix",
Expand All @@ -23,10 +24,12 @@
"@dqbd/tiktoken": "^1.0.2",
"@getmetal/metal-sdk": "^1.0.12",
"@pinecone-database/pinecone": "^0.0.10",
"@prisma/client": "^4.11.0",
"@supabase/supabase-js": "^2.10.0",
"chromadb": "^1.3.0",
"js-yaml": "^4.1.0",
"langchain": "workspace:*",
"prisma": "^4.11.0",
"sqlite3": "^5.1.4",
"typeorm": "^0.3.12",
"zod": "^3.21.4"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Add DATABASE_URL to .env file in this directory
DATABASE_URL=postgresql://[USERNAME]:[PASSWORD]@[ADDR]/[DBNAME]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
data
docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
db:
image: ankane/pgvector
ports:
- 5432:5432
volumes:
- ./data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=
- POSTGRES_USER=
- POSTGRES_DB=
30 changes: 30 additions & 0 deletions examples/src/indexes/vector_stores/prisma_vectorstore/prisma.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { PrismaVectorStore } from "langchain/vectorstores";
import { OpenAIEmbeddings } from "langchain/embeddings";
import { PrismaClient, Prisma, Document } from "@prisma/client";

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

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.at(0)?.metadata.content);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- CreateTable
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE "Document" (
"id" TEXT NOT NULL,
"content" TEXT NOT NULL,
"vector" vector,

CONSTRAINT "Document_pkey" PRIMARY KEY ("id")
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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
vector Unsupported("vector")?
}
21 changes: 13 additions & 8 deletions langchain/src/document.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
export interface DocumentParams {
export interface DocumentParams<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Metadata extends Record<string, any> = Record<string, any>
> {
pageContent: string;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
metadata: Record<string, any>;
metadata: Metadata;
}

/**
* Interface for interacting with a document.
*/
export class Document implements DocumentParams {
export class Document<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Metadata extends Record<string, any> = Record<string, any>
> implements DocumentParams
{
pageContent: string;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
metadata: Record<string, any>;
metadata: Metadata;

constructor(fields?: Partial<DocumentParams>) {
constructor(fields?: Partial<DocumentParams<Metadata>>) {
this.pageContent = fields?.pageContent ?? this.pageContent;
this.metadata = fields?.metadata ?? {};
this.metadata = fields?.metadata ?? ({} as Metadata);
}
}
1 change: 1 addition & 0 deletions langchain/src/vectorstores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { Chroma } from "./chroma.js";
export { PineconeStore } from "./pinecone.js";
export { VectorStore, SaveableVectorStore } from "./base.js";
export { SupabaseVectorStore } from "./supabase.js";
export { PrismaVectorStore } from "./prisma.js";
Loading

1 comment on commit 5ce8f2b

@vercel
Copy link

@vercel vercel bot commented on 5ce8f2b Apr 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.