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
12 changes: 6 additions & 6 deletions src/app/api/api_v1/endpoints/tutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ async def tutor_search(
]
file_content_str = "\n\n".join(file_content_str)

print(file_content_str)

messages = [
{"role": "system", "content": extractor_prompt},
{"role": "assistant", "content": file_content_str},
Expand Down Expand Up @@ -123,9 +121,11 @@ async def tutor_search(


@router.post("/syllabus")
async def create_syllabus(body: TutorSearchResponse) -> SyllabusResponse:
result = await tutor_manager(body)
async def create_syllabus(
body: TutorSearchResponse, lang: str = "en"
) -> SyllabusResponse:
results = await tutor_manager(body, lang)

# TODO: handle errors
# TODO: mae sure documents are used

return SyllabusResponse(syllabus=result.content, documents=body.documents)
return SyllabusResponse(syllabus=results, documents=body.documents)
53 changes: 28 additions & 25 deletions src/app/services/tutor/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@
from autogen_core.memory import ListMemory
from autogen_core.models import ChatCompletionClient, SystemMessage, UserMessage

from src.app.services.tutor.models import (
Message,
MessageWithResources,
TaskResponse,
TutorSearchResponse,
)
from src.app.services.tutor.models import MessageWithResources, SyllabusResponseAgent
from src.app.services.tutor.utils import build_system_message
from src.app.utils.logger import logger as utils_logger

Expand Down Expand Up @@ -81,17 +76,10 @@ def __init__(self, model_client: ChatCompletionClient) -> None:
async def handle_documents_and_themes(
self, message: MessageWithResources, ctx: MessageContext
) -> None:
contents = []
for curr_content in message.content:
if isinstance(curr_content, TutorSearchResponse):
contents.append(curr_content.extracts)

themes = []
for curr_content in contents:
if isinstance(curr_content, TutorSearchResponse):
themes.extend(curr_content.extracts)
contents = "summary :".join(message.summary)
themes = ",".join(message.themes)

prompt = f"Using the content in TEXT CONTENTS, you generate a syllabus that is engaging and coherent in relation to the THEMES extracted from these contents. \n\nTEXT CONTENTS:\n{contents}\n\nTHEMES:\n{themes}"
prompt = f"Using the content in TEXT CONTENTS, you generate a syllabus that is engaging and coherent in relation to the THEMES extracted from these contents. The syllabus should be written in lang: {message.lang} \n\nTEXT CONTENTS:\n{contents}\n\nTHEMES:\n{themes}"

start_time = time.time()
llm_result = await self._model_client.create(
Expand All @@ -110,11 +98,21 @@ async def handle_documents_and_themes(

await self.publish_message(
MessageWithResources(
content=response, resources=message.resources, source=self.id.type
content=response,
resources=message.resources,
source=self.id.type,
summary=message.summary,
themes=message.themes,
lang=message.lang,
),
topic_id=TopicId(sdg_expert_topic_type, source=self.id.key),
)

await self.publish_message(
SyllabusResponseAgent(content=response, source=self.id.type),
task_results_topic_id,
)


@type_subscription(topic_type=sdg_expert_topic_type)
class SDGExpertAgent(RoutedAgent):
Expand Down Expand Up @@ -167,7 +165,7 @@ async def handle_syllabus(
None
"""

prompt = f"Use these WeLearn documents: {message.resources} to integrate sustainability in this syllabus: {message.content}. You do not need to use ALL the information in the WeLearn documents, but ensure that sustainability integration is done in a way that is relevant and thematically linked to the discipline and the topics of the syllabus, that they are deeply embedded in the course content, and aligned with both the discipline and the broader educational goals. Add all WeLearn documents that you use in the REFERENCES section of the syllabus."
prompt = f"Use these WeLearn documents: {message.resources} to integrate sustainability in this syllabus: {message.content}. You do not need to use ALL the information in the WeLearn documents, but ensure that sustainability integration is done in a way that is relevant and thematically linked to the discipline and the topics of the syllabus, that they are deeply embedded in the course content, and aligned with both the discipline and the broader educational goals. Add all WeLearn documents that you use in the REFERENCES section of the syllabus. Keep the same language, lang: {message.lang}"
try:
start_time = time.time()
llm_result = await self._delegate.on_messages(
Expand All @@ -185,10 +183,15 @@ async def handle_syllabus(
)
assert isinstance(response, str)
await self.publish_message(
Message(content=response, source=self.id.type),
SyllabusResponseAgent(content=response, source=self.id.type),
topic_id=TopicId(pedagogical_engineer_topic_type, source=self.id.key),
)

await self.publish_message(
SyllabusResponseAgent(content=response, source=self.id.type),
task_results_topic_id,
)


@type_subscription(topic_type=pedagogical_engineer_topic_type)
class PedagogicalEngineerAgent(RoutedAgent):
Expand Down Expand Up @@ -232,17 +235,19 @@ def __init__(self, model_client: ChatCompletionClient, memory: ListMemory) -> No
self._model_client = model_client

@message_handler(match=lambda msg, ctx: msg.source.startswith("SDGExpert")) # type: ignore
async def handle_syllabus(self, message: Message, ctx: MessageContext) -> Message:
async def handle_syllabus(
self, message: SyllabusResponseAgent, ctx: MessageContext
) -> None:
"""
Handles the syllabus by improving on the pedagogical aspects and ensures that the competencies cited in the EU GreenComp framework are present in a coherent manner with the discipline and course content.
Args:
message (Message): The message containing the syllabus content.
message (SyllabusResponseAgent): The message containing the syllabus content.
ctx (MessageContext): The context of the message.
Returns:
None
"""

prompt = f"Ensure that the syllabus is pedagogically sound, aligns with competency-based learning, and optimizes student engagement and learning effectiveness. Ensure that the learning objectives, outcomes and the competencies and related in a logical and meaningful way, and that these overarching goals are accomplished through the course plan and activities, also ensure that the competencies cited in the EU GreenComp framework are present in the syllabus in a way that is coherent with the discipline and the course content.\n\nSYLLABUS:\n{message.content}"
prompt = f"Ensure that the syllabus is pedagogically sound, aligns with competency-based learning, and optimizes student engagement and learning effectiveness. Ensure that the learning objectives, outcomes and the competencies and related in a logical and meaningful way, and that these overarching goals are accomplished through the course plan and activities, also ensure that the competencies cited in the EU GreenComp framework are present in the syllabus in a way that is coherent with the discipline and the course content. Make sure to use the same language as the current syllabus. \n\nSYLLABUS:\n{message.content}"
start_time = time.time()
llm_result = await self._delegate.on_messages(
[TextMessage(content=prompt, source=self.id.key)],
Expand All @@ -256,8 +261,6 @@ async def handle_syllabus(self, message: Message, ctx: MessageContext) -> Messag
"agent_type=%s response_time=%s", self.id.type, end_time - start_time
)
await self.publish_message(
TaskResponse(result=response, task_id="pedagogical"),
SyllabusResponseAgent(content=response, source=self.id.type),
task_results_topic_id,
)

return Message(content=response)
15 changes: 9 additions & 6 deletions src/app/services/tutor/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,26 @@ class TutorSearchResponse(BaseModel):
documents: list[Document]


class SyllabusResponse(BaseModel):
syllabus: str
documents: list[Document]


class Message(BaseModel):
class SyllabusResponseAgent(BaseModel):
content: str
source: str = "default"


class SyllabusResponse(BaseModel):
syllabus: list[SyllabusResponseAgent]
documents: list[Document]


class MessageWithAnalysis(BaseModel):
content: Dict
source: str = "default"


class MessageWithResources(BaseModel):
lang: str = "en"
content: list[ExtractorOutput] | str
themes: list[str]
summary: list[str]
resources: List[Dict]
source: str = "default"

Expand Down
27 changes: 18 additions & 9 deletions src/app/services/tutor/tutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@
university_teacher_topic_type,
)
from src.app.services.tutor.models import (
Message,
MessageWithResources,
TaskResponse,
SyllabusResponseAgent,
TutorSearchResponse,
)
from src.app.services.tutor.utils import extract_doc_info
Expand All @@ -42,15 +41,21 @@
)


async def tutor_manager(content: TutorSearchResponse) -> Message:
queue = asyncio.Queue[TaskResponse]()
async def tutor_manager(
content: TutorSearchResponse, lang: str
) -> list[SyllabusResponseAgent]:
queue = asyncio.Queue[SyllabusResponseAgent]()

formatted_content = MessageWithResources(
content=content.extracts, resources=extract_doc_info(content.documents)
lang=lang,
content=content.extracts,
resources=extract_doc_info(content.documents),
themes=[theme for extract in content.extracts for theme in extract.themes],
summary=[extract.summary for extract in content.extracts],
)

async def collect_result(
_agent: ClosureContext, message: TaskResponse, ctx: MessageContext
_agent: ClosureContext, message: SyllabusResponseAgent, ctx: MessageContext
) -> None:
await queue.put(message)

Expand Down Expand Up @@ -117,9 +122,13 @@ async def collect_result(
)

await runtime.stop_when_idle()
response: TaskResponse = TaskResponse(task_id="", result="")
if not queue.empty():
responses = []
while not queue.empty():
response = await queue.get()
responses.append(response)

await runtime.close()
return Message(content=response.result)
return [
SyllabusResponseAgent(content=response.content, source=response.source)
for response in responses
]