refactor(brain): removed braintoupdate and added brain (#356)

* refactor(brain): removed braintoupdate and added brain

* feat(brain): updated
This commit is contained in:
Stan Girard 2023-06-21 10:16:44 +02:00 committed by GitHub
parent 3e753f2d56
commit 3d11e3fb51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 174 additions and 106 deletions

View File

@ -1,22 +1,109 @@
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from uuid import UUID from uuid import UUID
from models.settings import CommonsDep, common_dependencies
from pydantic import BaseModel from pydantic import BaseModel
class Brain(BaseModel): class Brain(BaseModel):
brain_id: Optional[UUID] = None brain_id: Optional[UUID]
name: str = "New Brain"
status: Optional[str]= "public"
model: Optional[str] = "gpt-3.5-turbo-0613"
temperature: Optional[float] = 0.0
max_tokens: Optional[int] = 256
class BrainToUpdate(BaseModel):
brain_id: UUID
name: Optional[str] = "New Brain" name: Optional[str] = "New Brain"
status: Optional[str] = "public" status: Optional[str] = "public"
model: Optional[str] = "gpt-3.5-turbo-0613" model: Optional[str] = "gpt-3.5-turbo-0613"
temperature: Optional[float] = 0.0 temperature: Optional[float] = 0.0
max_tokens: Optional[int] = 256 max_tokens: Optional[int] = 256
file_sha1: Optional[str] = "" file_sha1: Optional[str] = ""
_commons: Optional[CommonsDep] = None
class Config:
arbitrary_types_allowed = True
@property
def commons(self) -> CommonsDep:
if not self._commons:
self.__class__._commons = common_dependencies()
return self._commons
@classmethod
def create(cls, *args, **kwargs):
commons = common_dependencies()
return cls(commons=commons, *args, **kwargs)
def get_user_brains(self, user_id):
response = (
self.commons["supabase"]
.from_("brains_users")
.select("id:brain_id, brains (id: brain_id, name)")
.filter("user_id", "eq", user_id)
.execute()
)
return [item["brains"] for item in response.data]
def get_brain(self):
response = (
self.commons["supabase"]
.from_("brains")
.select("brainId:brain_id, brainName:brain_name")
.filter("brain_id", "eq", self.brain_id)
.execute()
)
return response.data
def get_brain_details(self):
response = (
self.commons["supabase"]
.from_("brains")
.select("id:brain_id, name, *")
.filter("brain_id", "eq", self.brain_id)
.execute()
)
return response.data
def delete_brain(self):
self.commons["supabase"].table("brains").delete().match(
{"brain_id": self.brain_id}
).execute()
@classmethod
def create_brain(cls, name):
commons = common_dependencies()
response = commons["supabase"].table("brains").insert({"name": name}).execute()
return response.data
def create_brain_user(self, brain_id, user_id, rights):
response = (
self.commons["supabase"]
.table("brains_users")
.insert({"brain_id": brain_id, "user_id": user_id, "rights": rights})
.execute()
)
return response.data
def create_brain_vector(self, vector_id):
response = (
self.commons["supabase"]
.table("brains_users")
.insert({"brain_id": self.brain_id, "vector_id": vector_id})
.execute()
)
return response.data
def get_vector_ids_from_file_sha1(self, file_sha1: str):
vectorsResponse = (
self.commons["supabase"]
.table("vectors")
.select("id")
.filter("metadata->>file_sha1", "eq", file_sha1)
.execute()
)
return vectorsResponse.data
def update_brain_fields(self):
self.commons["supabase"].table("brains").update({"name": self.name}).match(
{"brain_id": self.brain_id}
).execute()
def update_brain_with_file(self, file_sha1: str):
vector_ids = self.get_vector_ids_from_file_sha1(file_sha1)
for vector_id in vector_ids:
self.create_brain_vector(vector_id)

View File

@ -6,12 +6,10 @@ from uuid import UUID
from auth.auth_bearer import AuthBearer, get_current_user from auth.auth_bearer import AuthBearer, get_current_user
from fastapi import APIRouter, Depends, Request from fastapi import APIRouter, Depends, Request
from logger import get_logger from logger import get_logger
from models.brains import Brain, BrainToUpdate from models.brains import Brain
from models.settings import CommonsDep, common_dependencies from models.settings import CommonsDep, common_dependencies
from models.users import User from models.users import User
from utils.brains import (create_brain, create_brain_user, delete_brain, from pydantic import BaseModel
get_brain_details, get_user_brains,
update_brain_fields, update_brain_with_file)
from utils.users import fetch_user_id_from_credentials from utils.users import fetch_user_id_from_credentials
logger = get_logger(__name__) logger = get_logger(__name__)
@ -19,6 +17,16 @@ logger = get_logger(__name__)
brain_router = APIRouter() brain_router = APIRouter()
class BrainToUpdate(BaseModel):
brain_id: UUID
name: Optional[str] = "New Brain"
status: Optional[str] = "public"
model: Optional[str] = "gpt-3.5-turbo-0613"
temperature: Optional[float] = 0.0
max_tokens: Optional[int] = 256
file_sha1: Optional[str] = ""
# get all brains # get all brains
@brain_router.get("/brains", dependencies=[Depends(AuthBearer())], tags=["Brain"]) @brain_router.get("/brains", dependencies=[Depends(AuthBearer())], tags=["Brain"])
async def brain_endpoint(current_user: User = Depends(get_current_user)): async def brain_endpoint(current_user: User = Depends(get_current_user)):
@ -32,12 +40,16 @@ async def brain_endpoint(current_user: User = Depends(get_current_user)):
containing the brain ID and brain name for each brain. containing the brain ID and brain name for each brain.
""" """
commons = common_dependencies() commons = common_dependencies()
user_id = fetch_user_id_from_credentials(commons, {"email": current_user.email}) brain = Brain()
brains = get_user_brains(commons, user_id) user_id = fetch_user_id_from_credentials(commons, {"email": current_user.email})
brains = brain.get_user_brains(user_id)
return {"brains": brains} return {"brains": brains}
# get one brain # get one brain
@brain_router.get("/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]) @brain_router.get(
"/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]
)
async def brain_endpoint(brain_id: UUID): async def brain_endpoint(brain_id: UUID):
""" """
Retrieve details of a specific brain by brain ID. Retrieve details of a specific brain by brain ID.
@ -48,29 +60,50 @@ async def brain_endpoint(brain_id: UUID):
This endpoint retrieves the details of a specific brain identified by the provided brain ID. It returns the brain ID and its This endpoint retrieves the details of a specific brain identified by the provided brain ID. It returns the brain ID and its
history, which includes the brain messages exchanged in the brain. history, which includes the brain messages exchanged in the brain.
""" """
commons = common_dependencies() brain = Brain(brain_id=brain_id)
brains = get_brain_details(commons, brain_id) brains = brain.get_brain_details()
if len(brains) > 0: if len(brains) > 0:
return {"brainId": brain_id, "brainName": brains[0]['name'], "status": brains[0]['status']} return {
"brainId": brain_id,
"brainName": brains[0]["name"],
"status": brains[0]["status"],
}
else: else:
return {"error": f'No brain found with brain_id {brain_id}'} return {"error": f"No brain found with brain_id {brain_id}"}
# delete one brain # delete one brain
@brain_router.delete("/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]) @brain_router.delete(
"/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]
)
async def brain_endpoint(brain_id: UUID): async def brain_endpoint(brain_id: UUID):
""" """
Delete a specific brain by brain ID. Delete a specific brain by brain ID.
""" """
commons = common_dependencies() brain = Brain(brain_id=brain_id)
delete_brain(commons, brain_id) brain.delete_brain()
return {"message": f"{brain_id} has been deleted."} return {"message": f"{brain_id} has been deleted."}
class BrainObject(BaseModel):
brain_id: Optional[UUID]
name: Optional[str] = "New Brain"
status: Optional[str] = "public"
model: Optional[str] = "gpt-3.5-turbo-0613"
temperature: Optional[float] = 0.0
max_tokens: Optional[int] = 256
file_sha1: Optional[str] = ""
# create new brain # create new brain
@brain_router.post("/brains", dependencies=[Depends(AuthBearer())], tags=["Brain"]) @brain_router.post("/brains", dependencies=[Depends(AuthBearer())], tags=["Brain"])
async def brain_endpoint(request: Request, brain: Brain, current_user: User = Depends(get_current_user)): async def brain_endpoint(
request: Request,
brain: BrainObject,
current_user: User = Depends(get_current_user),
):
""" """
Create a new brain with given Create a new brain with given
name name
status status
model model
@ -78,32 +111,43 @@ async def brain_endpoint(request: Request, brain: Brain, current_user: User = De
temperature temperature
In the brains table & in the brains_users table and put the creator user as 'Owner' In the brains table & in the brains_users table and put the creator user as 'Owner'
""" """
commons = common_dependencies() commons = common_dependencies()
user_id = fetch_user_id_from_credentials(commons, {"email": current_user.email}) brain = Brain(name=brain.name)
created_brain = create_brain(commons, brain)[0] user_id = fetch_user_id_from_credentials(commons, {"email": current_user.email})
created_brain = brain.create_brain(brain.name)[0]
# create a brain X user entry # create a brain X user entry
create_brain_user(commons, created_brain['brain_id'], user_id, rights='Owner') brain.create_brain_user(created_brain["brain_id"], user_id, rights="Owner")
return {"id": created_brain["brain_id"], "name": created_brain["name"]}
return {"id": created_brain['brain_id'], "name": created_brain['name']}
# update existing brain # update existing brain
@brain_router.put("/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]) @brain_router.put(
async def brain_endpoint(request: Request, brain_id: UUID, brain: BrainToUpdate, fileName: Optional[str], current_user: User = Depends(get_current_user)): "/brains/{brain_id}", dependencies=[Depends(AuthBearer())], tags=["Brain"]
)
async def brain_endpoint(
request: Request,
brain_id: UUID,
input_brain: Brain,
fileName: Optional[str],
current_user: User = Depends(get_current_user),
):
""" """
Update an existing brain with new brain parameters/files. Update an existing brain with new brain parameters/files.
If the file is contained in Add file to brain : If the file is contained in Add file to brain :
if given a fileName/ file sha1 / -> add all the vector Ids to the brains_vectors if given a fileName/ file sha1 / -> add all the vector Ids to the brains_vectors
Modify other brain fields: Modify other brain fields:
name, status, model, max_tokens, temperature name, status, model, max_tokens, temperature
Return modified brain ? No need -> do an optimistic update Return modified brain ? No need -> do an optimistic update
""" """
commons = common_dependencies() commons = common_dependencies()
brain = Brain(brain_id=brain_id)
# Add new file to brain , il file_sha1 already exists in brains_vectors -> out (not now) # Add new file to brain , il file_sha1 already exists in brains_vectors -> out (not now)
if brain.file_sha1 : if brain.file_sha1:
# add all the vector Ids to the brains_vectors with the given brain.brain_id # add all the vector Ids to the brains_vectors with the given brain.brain_id
update_brain_with_file(commons, brain_id= brain.brain_id, file_sha1=brain.file_sha1) brain.update_brain_with_file(file_sha1=input_brain.file_sha1)
print("brain:", brain) print("brain:", brain)
update_brain_fields(commons, brain) brain.update_brain_fields(commons, brain)
return {"message": f"Brain {brain_id} has been updated."} return {"message": f"Brain {brain_id} has been updated."}

View File

@ -1,65 +0,0 @@
from uuid import UUID
from fastapi import APIRouter
from logger import get_logger
from models.brains import Brain, BrainToUpdate
from models.users import User
from models.settings import CommonsDep
from utils.users import fetch_user_id_from_credentials
logger = get_logger(__name__)
brain_router = APIRouter()
def get_user_brains(commons: CommonsDep, user_id):
response = commons['supabase'].from_('brains_users') \
.select('id:brain_id, brains (id: brain_id, name)') \
.filter('user_id', 'eq', user_id) \
.execute()
return [item['brains'] for item in response.data]
def get_brain(commons: CommonsDep, brain_id):
response = commons['supabase'].from_('brains').select('brainId:brain_id, brainName:brain_name').filter("brain_id", "eq", brain_id).execute()
return response.data
def get_brain_details(commons: CommonsDep, brain_id):
response = commons['supabase'].from_('brains').select('id:brain_id, name, *').filter("brain_id", "eq", brain_id).execute()
return response.data
def delete_brain(commons: CommonsDep, brain_id):
# Does it also delete it in brains_users and brains_vectors ?
commons['supabase'].table("brains").delete().match({"brain_id": brain_id}).execute()
def create_brain(commons: CommonsDep, brain = Brain):
response = commons['supabase'].table("brains").insert(
{"name": brain.name}).execute()
return response.data
def create_brain_user(commons: CommonsDep, brain_id, user_id, rights):
response = commons['supabase'].table("brains_users").insert(
{ "brain_id": brain_id, "user_id": user_id, "rights": rights}).execute()
return response.data
def create_brain_vector(commons: CommonsDep, brain_id, vector_id):
response = commons['supabase'].table("brains_users").insert(
{ "brain_id": brain_id, "vector_id": vector_id}).execute()
return response.data
def get_vector_ids_from_file_sha1(commons: CommonsDep, file_sha1: str):
vectorsResponse = commons['supabase'].table("vectors").select("id").filter("metadata->>file_sha1", "eq", file_sha1) \
.execute()
print('vectorsResponse', vectorsResponse.data)
return vectorsResponse.data
def update_brain_fields(commons: CommonsDep, brain: BrainToUpdate):
# Need to only get the not undefined brain fields passed Optional['Brain'] -> create a BrainToUpdate type
commons['supabase'].table("brains").update(
{ "name": brain.name}).match({"brain_id": brain.brain_id}).execute()
logger.info(f"Brain {brain.brain_id} updated")
def update_brain_with_file(commons: CommonsDep,brain_id:UUID , file_sha1: str ):
# add all the vector Ids to the brains_vectors with the given brain.brain_id
vector_ids = get_vector_ids_from_file_sha1(commons, file_sha1)
for vector_id in vector_ids:
create_brain_vector(commons, brain_id=brain_id, vector_id = vector_id)

2
frontend/.dockerignore Normal file
View File

@ -0,0 +1,2 @@
.next/
node_modules/