Skip to content

Commit

Permalink
Improve breaking roadmap into modules
Browse files Browse the repository at this point in the history
  • Loading branch information
lcarvajal committed Jul 27, 2024
1 parent f27fc6e commit 92077a4
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 20 deletions.
28 changes: 18 additions & 10 deletions app/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@router.get("/")
def hello():
"""Hello world route to make sure the app is working correctly"""
return {"msg": "Hello World!"}
return {"msg": "Welcome to the never bored learning api!"}

# Users

Expand Down Expand Up @@ -163,14 +163,15 @@ def follow_roadmap(firebase_user: Annotated[dict, Depends(get_firebase_user_from

# Modules

def create_resources_using_ragsearch_for_submodule(submodule_id, db):
def create_resources_using_ragsearch_for_submodule(roadmap_title: str, module_description: str, submodule_id: int, db):
submodule = crud.get_submodule_by_id_with_resources(db, submodule_id)

if len(submodule.resources) > 0:
print("Submodule already populated")
return

search_response = ragsearch.get_search_resources(submodule.description)
query = llm.get_query_to_find_learning_resources(roadmap_title=roadmap_title, module_description=module_description, submodule_description=submodule.description)
search_response = ragsearch.get_search_resources(query)
rag_resources = search_response["results"]
resources = []

Expand All @@ -191,10 +192,10 @@ def create_resources_using_ragsearch_for_submodule(submodule_id, db):

return resources

def create_resources_using_ragsearch_for_module(module_id, db):
def create_resources_using_ragsearch_for_module(roadmap_title, module_id, db):
module = crud.get_module_by_id_with_submodules_and_resources(db, module_id)
for submodule in module.submodules:
create_resources_using_ragsearch_for_submodule(submodule, db)
create_resources_using_ragsearch_for_submodule(roadmap_title, module.decription, submodule.id, db)

@router.post("/roadmaps/{roadmap_id}/modules/{module_id}/populate")
async def populate_module_with_submodules_and_resources(firebase_user: Annotated[dict, Depends(get_firebase_user_from_token)], roadmap_id: int, module_id: int, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
Expand Down Expand Up @@ -230,22 +231,29 @@ async def populate_module_with_submodules_and_resources(firebase_user: Annotated

submodules.append(submodule)

background_tasks.add_task(create_resources_using_ragsearch_for_module, module.id, db)
background_tasks.add_task(create_resources_using_ragsearch_for_module, roadmap.title, module.id, db)
return submodules

# Submodules
@router.post("/submodules/{submodule_id}/populate")
def populate_submodule_with_resources(firebase_user: Annotated[dict, Depends(get_firebase_user_from_token)], submodule_id: int, db: Session = Depends(get_db)):
print("heya")
@router.post("/roadmaps/{roadmap_id}/modules/{module_id}/submodules/{submodule_id}/populate")
def populate_submodule_with_resources(firebase_user: Annotated[dict, Depends(get_firebase_user_from_token)], roadmap_id: int, module_id: int, submodule_id: int, db: Session = Depends(get_db)):
roadmap = crud.get_roadmap_by_id(db, roadmap_id)
module = crud.get_module_by_id(db, module_id)
submodule = crud.get_submodule_by_id_with_resources(db, submodule_id)

if roadmap is None:
raise HTTPException(status_code=404, detail="Roadmap not found")

if module is None:
raise HTTPException(status_code=404, detail="Module not found")

if submodule is None:
raise HTTPException(status_code=404, detail="Submodule not found")

if len(submodule.resources) > 0:
raise HTTPException(status_code=400, detail="Submodule already populated")

resources = create_resources_using_ragsearch_for_submodule(submodule.id, db)
resources = create_resources_using_ragsearch_for_submodule(roadmap.title, module.description, submodule.id, db)

return resources

12 changes: 9 additions & 3 deletions app/utils/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,20 @@ def create_module(db: Session, module: roadmap_schema.ModuleCreate):
db.refresh(db_module)
return db_module

def get_module_by_id(db: Session, module_id: int):
return db.query(models.roadmap.Module).filter(models.roadmap.Module.id == module_id).first()

def get_module_by_id_with_submodules_and_resources(db: Session, module_id: int):
module = db.query(models.roadmap.Module).filter(models.roadmap.Module.id == module_id).first()
submodules = db.query(models.roadmap.Submodule).filter(models.roadmap.Submodule.module_id == module_id).all()

for submodule in submodules:
submodule.resources = db.query(models.roadmap.Resource).filter(models.roadmap.Resource.submodule_id == submodule.id).all()
if len(submodules) > 0:
for submodule in submodules:
submodule.resources = db.query(models.roadmap.Resource).filter(models.roadmap.Resource.submodule_id == submodule.id).all()

module.submodules = submodules
module.submodules = submodules
else:
module.submodules = []

return module

Expand Down
24 changes: 21 additions & 3 deletions app/utils/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
def get_roadmap(learning_goal: str):
model = ChatOpenAI()

class Module(BaseModel):
class Topic(BaseModel):
title: str
description: str

class StudyPlan(BaseModel):
learning_goal: str
title: str
modules: List[Module]
modules: List[Topic]

parser = JsonOutputParser(pydantic_object=StudyPlan)

prompt = PromptTemplate(
template="Break down the learning goal into a study plan. First, list all the topics required to master the learning goal. Then organize them into modules: \n{format_instructions}\n{learning_goal}\n",
template="Create a study plan by listing all the topics required to master the learning goal. The title should describe the topic (ex. 'Basic Music Theory'). The description should give more info on the topic (ex. Understanding notes, scales, and rhythm): \n{format_instructions}\n{learning_goal}\n",
input_variables=["learning_goal"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
Expand Down Expand Up @@ -52,3 +52,21 @@ class Module(BaseModel):
chain = prompt | model | parser
module = chain.invoke({"module": module})
return module["submodules"]

def get_query_to_find_learning_resources(roadmap_title: str, module_description: str, submodule_description: str):
model = ChatOpenAI()

class Query(BaseModel):
query: str

parser = JsonOutputParser(pydantic_object=Query)

prompt = PromptTemplate(
template="A user is learning the following. Create a search query that will be used to find learning resources for the sub module. \n\n\nStudy plan: {roadmap_title}\n\nModule: {module_description}\n\n Sub module: {submodule_description}\n",
input_variables=["roadmap_title", "module_description", "submodule_description"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)

chain = prompt | model | parser
query = chain.invoke({"roadmap_title": roadmap_title, "module_description": module_description, "submodule_description": submodule_description})
return query["query"]
6 changes: 2 additions & 4 deletions app/utils/ragsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@
tavily_key = os.getenv("TAVILY_API_KEY")
tavily_client = TavilyClient(api_key=tavily_key)

def get_search_resources(learning_topic: str):
prompt = "Give me resources on `" + learning_topic + "`"

return tavily_client.search(prompt)
def get_search_resources(query: str):
return tavily_client.search(query)

0 comments on commit 92077a4

Please sign in to comment.