Skip to content

Commit

Permalink
feat(ui): Utilize OpenAI for backend (#553)
Browse files Browse the repository at this point in the history
- Changes naming convention to use threads instead of conversations
- Refactors to use OpenAI types for threads, messages, and assistants
- Refactor to no longer save threads, messages, and assistants directly to Supabase, but instead uses OpenAI - endpoints
- Bug fixes for AssistantTile text, Assistant Avatar uploading
- Adds new mocking setups for testsport

---------

Co-authored-by: John Alling <john.alling@defenseunicorns.com>
Co-authored-by: Jon Perry <yrrepnoj@gmail.com>
  • Loading branch information
3 people committed May 25, 2024
1 parent 840f49a commit 5371956
Show file tree
Hide file tree
Showing 96 changed files with 3,153 additions and 2,204 deletions.
115 changes: 23 additions & 92 deletions packages/supabase/migrations/20240322174521_ui_sql_schema.sql
Original file line number Diff line number Diff line change
@@ -1,120 +1,51 @@
-- Create tables
create table conversations (
id uuid primary key DEFAULT uuid_generate_v4(),
user_id uuid references auth.users not null,
label text,
inserted_at timestamp with time zone default timezone('utc'::text, now()) not null
);

create table messages (
id uuid primary key DEFAULT uuid_generate_v4(),
user_id uuid references auth.users not null,
conversation_id uuid references conversations on delete cascade not null,
role text check (role in ('system', 'user', 'assistant', 'function', 'data', 'tool')),
content text,
inserted_at timestamp with time zone default timezone('utc'::text, now()) not null
-- Tables
create table public.profiles (
id uuid references auth.users not null primary key,
full_name text,
thread_ids text array DEFAULT '{}'
);


create table profiles (
id uuid references auth.users not null primary key,
updated_at timestamp with time zone,
username text unique,
full_name text,
avatar_url text,
website text,
constraint username_length check (char_length(username) >= 3)
);

create table assistants (
id uuid primary key DEFAULT uuid_generate_v4(),
object text check (object in ('assistant')),
name varchar(255),
description varchar(512),
model varchar(255) not null,
instructions TEXT,
tools jsonb,
tool_resources jsonb,
metadata jsonb,
temperature float,
top_p float,
response_format jsonb,
created_at timestamp with time zone default timezone('utc'::text, now()) not null
);

-- Set up Storage!
-- Storage
insert into storage.buckets
(id, name, public)
values
('assistant_avatars', 'assistant_avatars', true);

-- These are user profiles avatars, currently not used by app and will be removed soon
insert into storage.buckets (id, name)
values ('avatars', 'avatars');

-- RLS policies
alter table conversations enable row level security;
alter table messages enable row level security;
alter table profiles enable row level security;
alter table assistants enable row level security;

-- Policies for conversations
create policy "Individuals can create conversations." on conversations for
insert with check (auth.uid() = user_id);
create policy "Individuals can view their own conversations. " on conversations for
select using (auth.uid() = user_id);
create policy "Individuals can update their own conversations." on conversations for
update using (auth.uid() = user_id);
create policy "Individuals can delete their own conversations." on conversations for
delete using (auth.uid() = user_id);
alter table public.profiles enable row level security;

-- Policies for messages
create policy "Individuals can view their own messages." on messages for
select using (auth.uid() = user_id);
create policy "Individuals can create messages." on messages for
insert with check (auth.uid() = user_id);
create policy "Individuals can update their own messages." on messages for
update using (auth.uid() = user_id);
create policy "Individuals can delete their own messages." on messages for
delete using (auth.uid() = user_id);

-- Policies for profiles
create policy "Public profiles are viewable by everyone." on profiles
for select using (true);
create policy "Users can view their own profiles" on profiles
for select using (auth.uid() = id);
create policy "Users can insert their own profile." on profiles
for insert with check (auth.uid() = id);
for insert with check (auth.uid() = id);
create policy "Users can update own profile." on profiles
for update using (auth.uid() = id);
for update using (auth.uid() = id);

-- Policies for assistants
create policy "Individuals can view their own assistants." ON assistants
for select using ((metadata ->> 'created_by') = auth.uid()::text);
create policy "Individuals can create assistants." on assistants for
insert with check ((metadata ->> 'created_by') = auth.uid()::text);
create policy "Individuals can update their own assistants." on assistants for
update using ((metadata ->> 'created_by') = auth.uid()::text);
create policy "Individuals can delete their own assistants." on assistants for
delete using ((metadata ->> 'created_by') = auth.uid()::text);

-- Policies for storage.
create policy "Avatar images are publicly accessible." on storage.objects
for select using (bucket_id = 'avatars');
create policy "Anyone can upload an avatar." on storage.objects
for insert with check (bucket_id = 'avatars');
create policy "Anyone can update their own avatar." on storage.objects
for update using (auth.uid() = owner) with check (bucket_id = 'avatars');
-- Policies for storage

create policy "Assistant Avatar images are publicly accessible." on storage.objects
for select using (bucket_id = 'assistant_avatars');
create policy "Anyone can upload an assistant avatar." on storage.objects
for insert with check (bucket_id = 'assistant_avatars');
for insert with check (bucket_id = 'assistant_avatars');
create policy "Anyone can update their own assistant avatars." on storage.objects
for update using (auth.uid() = owner) with check (bucket_id = 'assistant_avatars');


-- Triggers

-- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth.
-- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details.
create function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id, full_name, avatar_url)
values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url');
return new;
insert into public.profiles (id, full_name)
values (new.id, new.raw_user_meta_data->>'full_name');
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- First, rename the existing table to keep a backup
ALTER TABLE profiles RENAME TO profiles_old;

-- Create the new table with the required structure
CREATE TABLE public.profiles (
id uuid REFERENCES auth.users NOT NULL PRIMARY KEY,
full_name text,
thread_ids text[] DEFAULT '{}'
);

-- Insert data from the old table to the new one (only the required columns)
INSERT INTO public.profiles (id, full_name)
SELECT id, full_name
FROM profiles_old;

-- Drop the old table if the data transfer is successful
-- DROP TABLE profiles_old;
30 changes: 30 additions & 0 deletions packages/supabase/migrations/20240523233951_0.8_ui_migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
DO $$
BEGIN
BEGIN
DROP TABLE IF EXISTS messages;
END;
BEGIN
DROP TABLE IF EXISTS conversations;
END;
END $$;

-- Drop the existing trigger
drop trigger if exists on_auth_user_created on auth.users;

-- Drop the existing function
drop function if exists public.handle_new_user();

-- Create the new function without the avatar_url field
create function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id, full_name)
values (new.id, new.raw_user_meta_data->>'full_name');
return new;
end;
$$ language plpgsql security definer;

-- Recreate the trigger
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
10 changes: 10 additions & 0 deletions src/leapfrogai_ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,13 @@ To get the MFA secret, create your new Keycloak user with the normal Keycloak lo
When scanning the QR code, use an app that lets you see the url of the QR code. The secret is contained in that URL.

Login flow was adapted from [this reference](https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit?database-method=sql)

### Using OpenAI

You can use OpenAI instead of Leapfrog API by changing these environment variables:

```
DEFAULT_MODEL=gpt-3.5-turbo
LEAPFROGAI_API_BASE_URL=https://api.openai.com/v1
LEAPFROGAI_API_KEY=<your-openai-api-key>
```
Loading

0 comments on commit 5371956

Please sign in to comment.