Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 228 additions & 37 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ langgraph-checkpoint-postgres = "^2.0.23"
azure-ai-inference = "^1.0.0b9"
azure-identity = "^1.25.0"
psycopg = {extras = ["binary"], version = "^3.2.10"}
welearn-database = "1.3.0"
welearn-database = "1.4.0"
bs4 = "^0.0.2"
urllib3 = "^2.6.3"
refinedoc = "^1.0.1"
Expand Down
9 changes: 9 additions & 0 deletions src/app/api/api_v1/endpoints/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,12 @@ async def update_clicked_doc_from_chat_message(
) -> str:
await data_collection.register_document_click(body.doc_id, body.message_id)
return "updated"


@router.post("/syllabus_downloaded")
async def register_syllabus_download(
request: Request, data_collection=Depends(get_data_collection_service)
) -> str:
session_id = request.headers.get("X-Session-ID")
await data_collection.register_syllabus_download(session_id)
return "registered"
30 changes: 26 additions & 4 deletions src/app/api/api_v1/endpoints/search.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
# src/app/api/api_v1/endpoints/search.py

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response
from fastapi import (
APIRouter,
BackgroundTasks,
Depends,
HTTPException,
Request,
Response,
)
from fastapi.concurrency import run_in_threadpool

from src.app.models.documents import Document
from src.app.models.search import (
EnhancedSearchQuery,
SDGFilter,
SearchMethods,
SearchOutput,
SearchQuery,
)
from src.app.services.data_collection import get_data_collection_service
from src.app.services.exceptions import (
CollectionNotFoundError,
EmptyQueryError,
Expand Down Expand Up @@ -185,23 +194,27 @@ async def multi_search_all_slices_by_lang(
"/by_document",
summary="search all documents",
description="Search by documents, returns only one result by document id",
response_model=list[Document] | None | str,
response_model=SearchOutput | None | str,
)
async def search_all(
request: Request,
background_tasks: BackgroundTasks,
response: Response,
qp: EnhancedSearchQuery = Depends(get_params),
sp: SearchService = Depends(get_search_service),
data_collection=Depends(get_data_collection_service),
):
try:
session_id = request.headers.get("X-Session-ID")

res = await sp.search_handler(
qp=qp, method=SearchMethods.BY_DOCUMENT, background_tasks=background_tasks
)

if not res:
logger.error("No results found")
response.status_code = 204
return []
return SearchOutput(search_message_id=None, docs=[])
except CollectionNotFoundError as e:
raise HTTPException(
status_code=404,
Expand All @@ -210,7 +223,16 @@ async def search_all(

response.status_code = 200

return res
search_message_id = await data_collection.register_search_data(
session_id=session_id,
query=qp.query,
sdg_filter=qp.sdg_filter,
corpora=qp.corpora,
search_results=res,
feature="search",
)

return SearchOutput(search_message_id=search_message_id, docs=res)


@router.post(
Expand Down
61 changes: 56 additions & 5 deletions src/app/api/api_v1/endpoints/tutor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
from typing import Annotated

import backoff
from fastapi import APIRouter, BackgroundTasks, Depends, File, Response, UploadFile
from fastapi import (
APIRouter,
BackgroundTasks,
Depends,
File,
Request,
Response,
UploadFile,
)

from src.app.api.dependencies import get_settings
from src.app.models.search import EnhancedSearchQuery
from src.app.services.abst_chat import get_chat_service
from src.app.services.data_collection import get_data_collection_service
from src.app.services.exceptions import NoResultsError
from src.app.services.helpers import extract_json_from_response
from src.app.services.search import SearchService, get_search_service
Expand All @@ -17,6 +26,7 @@
SyllabusFeedback,
SyllabusResponse,
SyllabusResponseAgent,
SyllabusUserUpdate,
TutorSearchResponse,
TutorSyllabusRequest,
)
Expand Down Expand Up @@ -147,7 +157,7 @@ async def tutor_search_extract(
return resp


@router.post("/search")
@router.post("/search", deprecated=True)
async def tutor_search(
files: Annotated[list[UploadFile], File()],
response: Response,
Expand Down Expand Up @@ -255,14 +265,28 @@ async def tutor_search(
)
@router.post("/syllabus")
async def create_syllabus(
body: TutorSyllabusRequest, lang: str = "en"
request: Request,
body: TutorSyllabusRequest,
lang: str = "en",
data_collection=Depends(get_data_collection_service),
) -> SyllabusResponse:
session_id = request.headers.get("X-Session-ID")
results = await tutor_manager(body, lang)

# TODO: handle errors

message_id = await data_collection.register_syllabus_data(
session_id=session_id,
input_data=body,
agent_answer=results[0].content if results else "",
feature="syllabus_creation",
)

return SyllabusResponse(
syllabus=results, documents=body.documents, extracts=body.extracts
syllabus=results,
documents=body.documents,
extracts=body.extracts,
syllabus_message_id=message_id,
)


Expand Down Expand Up @@ -317,8 +341,12 @@ async def create_syllabus(
)
@router.post("/syllabus/feedback")
async def handle_syllabus_feedback(
body: SyllabusFeedback, chatfactory=Depends(get_chat_service)
request: Request,
body: SyllabusFeedback,
chatfactory=Depends(get_chat_service),
data_collection=Depends(get_data_collection_service),
):
session_id = request.headers.get("X-Session-ID")

messages = [
{
Expand Down Expand Up @@ -347,6 +375,13 @@ async def handle_syllabus_feedback(

assert isinstance(syllabus, str)

await data_collection.register_syllabus_data(
session_id=session_id,
input_data=body,
agent_answer=syllabus,
feature="syllabus_feedback",
)

return SyllabusResponse(
syllabus=[SyllabusResponseAgent(content=syllabus)],
documents=body.documents,
Expand All @@ -356,3 +391,19 @@ async def handle_syllabus_feedback(
except Exception as e:
logger.error(f"Error in chat schema: {e}")
raise e


@router.post("/syllabus/user_update")
async def register_syllabus_user_update(
request: Request,
body: SyllabusUserUpdate,
data_collection=Depends(get_data_collection_service),
):
session_id = request.headers.get("X-Session-ID")

await data_collection.register_syllabus_update(
session_id=session_id,
syllabus_content=body.syllabus,
)

return {"message": "user update registered"}
10 changes: 9 additions & 1 deletion src/app/models/search.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import uuid
from enum import StrEnum, auto
from typing import Optional

from pydantic import BaseModel, Field
from qdrant_client.http.models import Range
from qdrant_client.http.models import Range, ScoredPoint
from qdrant_client.models import FieldCondition, Filter, MatchAny

from src.app.models.documents import Document
from src.app.utils.decorators import log_time_and_error_sync
from src.app.utils.logger import logger as logger_utils

logger = logger_utils(__name__)


class SearchOutput(BaseModel):
search_message_id: Optional[uuid.UUID] = None
docs: list[Document] | list[ScoredPoint] | None = None


class SDGFilter(BaseModel):
sdg_filter: list[int] | None = Field(
None,
Expand Down
Loading