diff --git a/Dockerfile b/Dockerfile index fa41f08..dc0a9e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,23 +2,17 @@ # Use an official Node.js runtime as the parent image FROM node:18 -# Set the working directory in the container to /app -WORKDIR /app +# Copy the monorepo +COPY . /app -# Copy package.json and package-lock.json to the working directory -COPY server/package*.json ./ +# Set the working directory in the container to /app/server +WORKDIR /app/ # Install any needed packages specified in package.json RUN npm install -# Bundle the app source code inside the Docker image -COPY server/ . - -# Build the project -RUN npm run build - # The app is served by Next.js on port 3000, so expose this port EXPOSE 3000 # Define the command to run the app -CMD ["npm", "start"] +CMD ["npm", "run", "dev", "--workspace=server"] diff --git a/README.md b/README.md index ae4c880..9343194 100644 --- a/README.md +++ b/README.md @@ -105,25 +105,32 @@ if is_leak_detected: ## Self-hosting -To self-host Rebuff, you need to set up the necessary providers like Pinecone, Supabase, and OpenAI. Follow the links below to set up each provider: +To self-host Rebuff, you need to set up the necessary providers like Pinecone, +Supabase, and OpenAI. Follow the links below to set up each provider: - [Pinecone](https://www.pinecone.io/) - [Supabase](https://supabase.io/) - [OpenAI](https://beta.openai.com/signup/) -Once you have set up the providers, you can start the Rebuff server using Docker. First, build the Docker image: +Once you have set up the providers, you'll need to stand up the relevant SQL and +vector databases on Supabase and Pinecone respectively. See the +[server README](server/README.md) for more information. + +Now you can start the Rebuff server using Docker. First, build the Docker image: ```bash docker build -t rebuff . ``` -Then, start the Docker container with the following command, replacing the placeholders with your actual API keys and environment variables: +Then, start the Docker container with the below command, +replacing the placeholders with your actual API keys, environment variables, and +desired server configurations. ```bash docker run -d -p 3000:3000 \ -e OPENAI_API_KEY= \ + -e MASTER_API_KEY=12345 \ -e BILLING_RATE_INT_10K= \ - -e MASTER_API_KEY= \ -e MASTER_CREDIT_AMOUNT= \ -e NEXT_PUBLIC_SUPABASE_ANON_KEY= \ -e NEXT_PUBLIC_SUPABASE_URL= \ @@ -131,11 +138,21 @@ docker run -d -p 3000:3000 \ -e PINECONE_ENVIRONMENT= \ -e PINECONE_INDEX_NAME= \ -e SUPABASE_SERVICE_KEY= \ + -e REBUFF_API=http://localhost:3000 \ --name rebuff rebuff ``` Now, the Rebuff server should be running at `http://localhost:3000`. + +### Server Configurations + +* `BILLING_RATE_INT_10K`: The amount of credits that should be deducted for +every request. The value is an integer, and 10k refers to a single dollar amount. +So if you set the value to 10000 then it will deduct 1 dollar per request. If you set +it to 1 then it will deduct 0.1 cents per request. + + ## How it works ![Sequence Diagram](https://github.com/woop/rebuff/assets/6728866/3d90ebb3-d149-42e8-b991-a46c46d5a9e7) diff --git a/server/README.md b/server/README.md index bcd4f42..db1d37f 100644 --- a/server/README.md +++ b/server/README.md @@ -1,5 +1,7 @@ # Rebuff.AI +## Tooling + - Frontend: - [Next.js](https://github.com/vercel/next.js) - a React framework for production. - [Tailwind](https://tailwindcss.com/) for styling and layout. @@ -7,4 +9,14 @@ - Backend: - [app.supabase.com](https://app.supabase.com/): hosted Postgres database with restful API for usage with Supabase.js. -TODO: Add more info about the project. +## Database Setup +In order to use the Rebuff server, you'll first need to: +1. Create relational database tables and functions to record user's credits and previous attempts +2. Create a vectorDB to record previous prompt embeddings for similarity searching + +### Supabase (Relational DB) +* The needed relational database tables can be found in [sql_setup/tables](sql_setup/tables) +* The needed relational database functions can be found in [sql_setup/functions](sql_setup/functions) + +### Pinecone (Vector DB) +* The pinecone index that you create must be of dimension 1536 \ No newline at end of file diff --git a/server/deduct_rate.sql b/server/sql_setup/functions/deduct_rate.sql similarity index 100% rename from server/deduct_rate.sql rename to server/sql_setup/functions/deduct_rate.sql diff --git a/server/sql_setup/functions/get_attempt_aggregates.sql b/server/sql_setup/functions/get_attempt_aggregates.sql new file mode 100644 index 0000000..6b3bfa7 --- /dev/null +++ b/server/sql_setup/functions/get_attempt_aggregates.sql @@ -0,0 +1,14 @@ +-- Return 3 aggregate columns from the public.attempts table + select jsonb_build_object('breaches',jsonb_build_object('total',total_breach_cnt,'user',user_breach_cnt),'detections',detections_cnt,'requests',user_requests_cnt) + FROM + (SELECT + -- sum of all rows where breach is true + coalesce(sum(case when breach then 1 else 0 end),0)+53 as total_breach_cnt, + -- sum of all rows where breach is true and user_id matches the provided user_id + sum(case when breach and user_id = $1 then 1 else 0 end) as user_breach_cnt, + -- sum of all rows where user_id matches the provided user_id + sum(case when user_id = $1 then 1 else 0 end) as user_requests_cnt, + -- sum of all rows where user_id matches provided user_id and 'is_injection' in the response jsonb field is set to true + sum(case when user_id = $1 and response->>'is_injection' = 'true' then 1 else 0 end) as detections_cnt + from public.attempts + where user_id = $1) a; \ No newline at end of file diff --git a/server/sql_setup/tables/accounts.sql b/server/sql_setup/tables/accounts.sql new file mode 100644 index 0000000..d27d92e --- /dev/null +++ b/server/sql_setup/tables/accounts.sql @@ -0,0 +1,10 @@ +create table + public.accounts ( + id uuid not null, + created_at timestamp with time zone null default now(), + name text null, + user_apikey text not null, + credits_total_cents_10k integer not null default 10000, + constraint accounts_pkey primary key (id), + constraint accounts_id_fkey foreign key (id) references auth.users (id) + ) tablespace pg_default; \ No newline at end of file diff --git a/server/sql_setup/tables/attempts.sql b/server/sql_setup/tables/attempts.sql new file mode 100644 index 0000000..8cc76b2 --- /dev/null +++ b/server/sql_setup/tables/attempts.sql @@ -0,0 +1,11 @@ +create table + public.attempts ( + id bigint generated by default as identity, + created_at timestamp with time zone null default now(), + user_id uuid null, + request jsonb null, + response jsonb null, + breach boolean null, + constraint attempts_pkey primary key (id), + constraint attempts_user_id_fkey foreign key (user_id) references auth.users (id) + ) tablespace pg_default; \ No newline at end of file diff --git a/server/sql_setup/tables/leak_logs.sql b/server/sql_setup/tables/leak_logs.sql new file mode 100644 index 0000000..7ba7442 --- /dev/null +++ b/server/sql_setup/tables/leak_logs.sql @@ -0,0 +1,12 @@ +create table + public.leak_logs ( + id bigint generated by default as identity, + account_id uuid not null, + created_at timestamp with time zone not null default now(), + user_input text not null, + completion text null, + canary_word text null, + metadata_json json null, + constraint leak_logs_pkey primary key (id), + constraint leak_logs_account_id_fkey foreign key (account_id) references accounts (id) + ) tablespace pg_default; \ No newline at end of file