mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-24 11:52:45 +03:00
refactor(brain): removed braintoupdate and added brain (#356)
* refactor(brain): removed braintoupdate and added brain * feat(brain): updated
This commit is contained in:
parent
3e753f2d56
commit
3d11e3fb51
@ -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)
|
||||||
|
@ -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."}
|
||||||
|
|
||||||
|
@ -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
2
frontend/.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.next/
|
||||||
|
node_modules/
|
Loading…
Reference in New Issue
Block a user