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

Implement Chroma Support #1

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/tim.svg?style=social&label=Follow%20%40Timothy%20Carambat)](https://twitter.com/tcarambat) [![](https://dcbadge.vercel.app/api/server/6UyHPeGZAC?compact=true&style=flat)](https://discord.gg/6UyHPeGZAC)

A full-stack application and tool suite that enables you to turn any document, resource, or piece of content into a piece of data that any LLM can use as reference during chatting. This application runs with very minimal overhead as by default the LLM and vectorDB are hosted remotely, but can be swapped for local instances. Currently this project supports Pinecone and OpenAI.
A full-stack application and tool suite that enables you to turn any document, resource, or piece of content into a piece of data that any LLM can use as reference during chatting. This application runs with very minimal overhead as by default the LLM and vectorDB are hosted remotely, but can be swapped for local instances. Currently this project supports Pinecone & ChromaDB for vector storage and OpenAI for chatting.

![Chatting](/images/screenshots/chat.png)
[view more screenshots](/images/screenshots/SCREENSHOTS.md)
Expand Down Expand Up @@ -38,7 +38,7 @@ This monorepo consists of three main sections:
- `yarn` and `node` on your machine
- `python` 3.8+ for running scripts in `collector/`.
- access to an LLM like `GPT-3.5`, `GPT-4`*.
- a [Pinecone.io](https://pinecone.io) free account*.
- a [Pinecone.io](https://pinecone.io) free account* **or** Local Chroma instance running.
*you can use drop in replacements for these. This is just the easiest to get up and running fast.

### How to get started
Expand Down
51 changes: 21 additions & 30 deletions frontend/src/components/DefaultChat/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ export default function DefaultChatContainer() {
const MESSAGES = [
<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand All @@ -34,9 +33,8 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand All @@ -51,17 +49,16 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
AnythingLLM can run totally locally on your machine with little
overhead you wont even notice it's there! No GPU needed. Cloud and
on-premises installtion is available as well.
on-premises installation is available as well.
<br />
The AI tooling ecosytem gets more powerful everyday. AnythingLLM
The AI tooling ecosystem gets more powerful everyday. AnythingLLM
makes it easy to use.
</p>
<a
Expand All @@ -79,9 +76,8 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-end ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-end ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-slate-200 dark:bg-amber-800 rounded-b-2xl rounded-tl-2xl rounded-tr-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand All @@ -93,9 +89,8 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand All @@ -122,24 +117,22 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-end ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-end ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-slate-200 dark:bg-amber-800 rounded-b-2xl rounded-tl-2xl rounded-tr-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Is this like an AI dropbox or something? What about chatting? It is
a chatbot isnt it?
a chatbot isn't it?
</p>
</div>
</div>
</React.Fragment>,

<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand Down Expand Up @@ -168,9 +161,8 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-end ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-end ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-slate-200 dark:bg-amber-800 rounded-b-2xl rounded-tl-2xl rounded-tr-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand All @@ -182,9 +174,8 @@ export default function DefaultChatContainer() {

<React.Fragment>
<div
className={`flex w-full mt-2 justify-start ${
popMsg ? "chat__message" : ""
}`}
className={`flex w-full mt-2 justify-start ${popMsg ? "chat__message" : ""
}`}
>
<div className="p-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-b-2xl rounded-tr-2xl rounded-tl-sm">
<p className="text-slate-800 dark:text-slate-200 font-semibold">
Expand Down
44 changes: 31 additions & 13 deletions frontend/src/components/Modals/Keys.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,38 @@ export default function KeysModal({ hideModal = noop }) {
/>
<div className="h-[2px] w-full bg-gray-200 dark:bg-stone-600" />
<ShowKey
name="Pinecone DB API Key"
value={settings?.PineConeKey ? "*".repeat(20) : ""}
valid={!!settings?.PineConeKey}
/>
<ShowKey
name="Pinecone DB Environment"
value={settings?.PineConeEnvironment}
valid={!!settings?.PineConeEnvironment}
/>
<ShowKey
name="Pinecone DB Index"
value={settings?.PinceConeIndex}
valid={!!settings?.PinceConeIndex}
name="Vector DB Choice"
value={settings?.VectorDB}
valid={!!settings?.VectorDB}
/>
{settings?.VectorDB === "pinecone" && (
<>
<ShowKey
name="Pinecone DB API Key"
value={settings?.PineConeKey ? "*".repeat(20) : ""}
valid={!!settings?.PineConeKey}
/>
<ShowKey
name="Pinecone DB Environment"
value={settings?.PineConeEnvironment}
valid={!!settings?.PineConeEnvironment}
/>
<ShowKey
name="Pinecone DB Index"
value={settings?.PineConeIndex}
valid={!!settings?.PineConeIndex}
/>
</>
)}
{settings?.VectorDB === "chroma" && (
<>
<ShowKey
name="Chroma Endpoint"
value={settings?.ChromaEndpoint}
valid={!!settings?.ChromaEndpoint}
/>
</>
)}
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Modals/ManageWorkspace.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function ManageWorkspace({ hideModal = noop, workspace }) {
const deleteWorkspace = async () => {
if (
!window.confirm(
`You are about to delete your entire ${workspace.name} workspace. This will remove all vector embeddings on your vector database.\n\nThe original source files will remiain untouched. This action is irreversible.`
`You are about to delete your entire ${workspace.name} workspace. This will remove all vector embeddings on your vector database.\n\nThe original source files will remain untouched. This action is irreversible.`
)
)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { memo, useEffect, useRef, useState } from "react";
import { AlertTriangle } from "react-feather";
import Jazzicon from "../../../../UserIcon";
import { decode as HTMLDecode } from "he";
import { v4 } from "uuid";

function PromptReply({
uuid,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"author": "Timothy Carambat (Mintplex Labs)",
"license": "MIT",
"scripts": {
"lint": "cd server && yarn lint && cd .. && cd frontend && yarn lint",
"setup": "cd server && yarn && cd .. && yarn setup:envs && echo \"Please run yarn dev:server and yarn dev:frontend in separate terminal tabs.\"",
"setup:envs": "cd server && cp -n .env.example .env.development && cd ../collector && cp -n .env.example .env && cd ..",
"dev:server": "cd server && yarn dev",
Expand Down
13 changes: 10 additions & 3 deletions server/.env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
SERVER_PORT=5000
OPEN_AI_KEY=
OPEN_MODEL_PREF='gpt-3.5-turbo'
# AUTH_TOKEN="hunter2" # This is the password to your application if remote hosting.
CACHE_VECTORS="true"

# Enable all below if you are using vector database: Chroma.
# VECTOR_DB="chroma"
# CHROMA_ENDPOINT='http://localhost:8000'

# Enable all below if you are using vector database: Pinecone.
VECTOR_DB="pinecone"
PINECONE_ENVIRONMENT=
PINECONE_API_KEY=
PINECONE_INDEX=
AUTH_TOKEN="hunter2" # This is the password to your application if remote hosting.
CACHE_VECTORS="true"
PINECONE_INDEX=
2 changes: 1 addition & 1 deletion server/.nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18.12.1
v18.13.0
17 changes: 8 additions & 9 deletions server/endpoints/chat.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const { reqBody } = require('../utils/http');
const { Workspace } = require('../models/workspace');
const { chatWithWorkspace } = require('../utils/chats');
const { reqBody } = require("../utils/http");
const { Workspace } = require("../models/workspace");
const { chatWithWorkspace } = require("../utils/chats");

function chatEndpoints(app) {
if (!app) return;

app.post('/workspace/:slug/chat', async (request, response) => {
const { slug } = request.params
const { message, mode = 'query' } = reqBody(request)
app.post("/workspace/:slug/chat", async (request, response) => {
const { slug } = request.params;
const { message, mode = "query" } = reqBody(request);
const workspace = await Workspace.get(`slug = '${slug}'`);
if (!workspace) {
response.sendStatus(400).end();
Expand All @@ -16,8 +16,7 @@ function chatEndpoints(app) {

const result = await chatWithWorkspace(workspace, message, mode);
response.status(200).json({ ...result });
})

});
}

module.exports = { chatEndpoints }
module.exports = { chatEndpoints };
56 changes: 34 additions & 22 deletions server/endpoints/system.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` })
const { Pinecone } = require('../utils/pinecone');
const { viewLocalFiles } = require('../utils/files');
require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` });
const { viewLocalFiles } = require("../utils/files");
const { getVectorDbClass } = require("../utils/helpers");

function systemEndpoints(app) {
if (!app) return;

app.get('/ping', (_, response) => {
app.get("/ping", (_, response) => {
response.sendStatus(200);
})
});

app.get('/setup-complete', (_, response) => {
app.get("/setup-complete", (_, response) => {
const vectorDB = process.env.VECTOR_DB || "pinecone";
const results = {
VectorDB: vectorDB,
OpenAiKey: !!process.env.OPEN_AI_KEY,
OpenAiModelPref: process.env.OPEN_MODEL_PREF || 'gpt-3.5-turbo',
PineConeEnvironment: process.env.PINECONE_ENVIRONMENT,
PineConeKey: !!process.env.PINECONE_API_KEY,
PinceConeIndex: process.env.PINECONE_INDEX,
}
response.status(200).json({ results })
})
OpenAiModelPref: process.env.OPEN_MODEL_PREF || "gpt-3.5-turbo",
...(vectorDB === "pinecone"
? {
PineConeEnvironment: process.env.PINECONE_ENVIRONMENT,
PineConeKey: !!process.env.PINECONE_API_KEY,
PineConeIndex: process.env.PINECONE_INDEX,
}
: {}),
...(vectorDB === "chroma"
? {
ChromaEndpoint: process.env.CHROMA_ENDPOINT,
}
: {}),
};
response.status(200).json({ results });
});

app.get('/system-vectors', async (_, response) => {
const vectorCount = await Pinecone.totalIndicies();
response.status(200).json({ vectorCount })
})
app.get("/system-vectors", async (_, response) => {
const VectorDb = getVectorDbClass();
const vectorCount = await VectorDb.totalIndicies();
response.status(200).json({ vectorCount });
});

app.get('/local-files', async (_, response) => {
const localFiles = await viewLocalFiles()
response.status(200).json({ localFiles })
})
app.get("/local-files", async (_, response) => {
const localFiles = await viewLocalFiles();
response.status(200).json({ localFiles });
});
}

module.exports = { systemEndpoints }
module.exports = { systemEndpoints };
Loading