diff --git a/src/knowledge/ingestion.py b/src/knowledge/ingestion.py index 1ef6894..76a4872 100644 --- a/src/knowledge/ingestion.py +++ b/src/knowledge/ingestion.py @@ -5,7 +5,6 @@ """ import logging -import os from pathlib import Path from src.config import settings @@ -91,7 +90,10 @@ def chunk_text( chunks.append("\n\n".join(current_chunk)) # Keep overlap overlap_text = "\n\n".join(current_chunk) - overlap_chars = overlap_text[-chunk_overlap:] if len(overlap_text) > chunk_overlap else overlap_text + if len(overlap_text) > chunk_overlap: + overlap_chars = overlap_text[-chunk_overlap:] + else: + overlap_chars = overlap_text current_chunk = [overlap_chars] if overlap_chars.strip() else [] current_length = len(overlap_chars) diff --git a/src/knowledge/vectorstore.py b/src/knowledge/vectorstore.py index 69b5cfd..28a2fcd 100644 --- a/src/knowledge/vectorstore.py +++ b/src/knowledge/vectorstore.py @@ -6,7 +6,6 @@ import json import logging -import math from pathlib import Path import numpy as np diff --git a/src/routes/courses.py b/src/routes/courses.py index 2f4680c..a519afd 100644 --- a/src/routes/courses.py +++ b/src/routes/courses.py @@ -3,7 +3,6 @@ import logging from fastapi import APIRouter, HTTPException -from fastapi.responses import JSONResponse from src.models.course import Course, GenerateCourseRequest from src.services.generation import get_generation_service diff --git a/src/services/cohere_client.py b/src/services/cohere_client.py index ea0bae5..5ea8d7a 100644 --- a/src/services/cohere_client.py +++ b/src/services/cohere_client.py @@ -20,7 +20,7 @@ class CohereClient: def __init__(self, api_key: str | None = None) -> None: self._api_key = api_key or settings.cohere_api_key - self._client = cohere.ClientV2(api_key=self._api_key) + self._client = cohere.AsyncClientV2(api_key=self._api_key) self._embed_model = settings.cohere_embed_model self._generate_model = settings.cohere_generate_model @@ -54,7 +54,7 @@ async def generate( messages.append({"role": "user", "content": prompt}) try: - response = self._client.chat( + response = await self._client.chat( model=self._generate_model, messages=messages, max_tokens=max_tokens, @@ -108,7 +108,11 @@ async def generate_json( logger.debug("Raw response: %s", raw[:500]) raise ValueError(f"Invalid JSON response from Cohere: {exc}") from exc - async def embed(self, texts: list[str], input_type: str = "search_document") -> list[list[float]]: + async def embed( + self, + texts: list[str], + input_type: str = "search_document", + ) -> list[list[float]]: """Generate embeddings for a list of texts. Args: @@ -125,7 +129,7 @@ async def embed(self, texts: list[str], input_type: str = "search_document") -> return [] try: - response = self._client.embed( + response = await self._client.embed( model=self._embed_model, texts=texts, input_type=input_type, diff --git a/src/services/embedding.py b/src/services/embedding.py index 7181b4a..797ee05 100644 --- a/src/services/embedding.py +++ b/src/services/embedding.py @@ -34,7 +34,8 @@ async def embed_documents(self, texts: list[str]) -> list[list[float]]: ) all_embeddings.extend(embeddings) - logger.info("Embedded %d documents in %d batches", len(texts), (len(texts) - 1) // batch_size + 1) + num_batches = (len(texts) - 1) // batch_size + 1 + logger.info("Embedded %d documents in %d batches", len(texts), num_batches) return all_embeddings async def embed_query(self, query: str) -> list[float]: diff --git a/src/services/feedback_engine.py b/src/services/feedback_engine.py index 5a115b9..6b1c7e1 100644 --- a/src/services/feedback_engine.py +++ b/src/services/feedback_engine.py @@ -114,7 +114,10 @@ async def quick_feedback( return f"Correct! {question.explanation}" correct_option = question.options[question.correct_index] - user_option = question.options[user_answer] if 0 <= user_answer < len(question.options) else "N/A" + if 0 <= user_answer < len(question.options): + user_option = question.options[user_answer] + else: + user_option = "N/A" return ( f"Incorrect. You chose '{user_option}', but the correct answer is '{correct_option}'. " f"{question.explanation}" diff --git a/src/services/generation.py b/src/services/generation.py index fb3a042..6067c9f 100644 --- a/src/services/generation.py +++ b/src/services/generation.py @@ -2,13 +2,13 @@ import logging +from src.knowledge.vectorstore import get_vectorstore from src.models.course import Course, CourseModule, GenerateCourseRequest from src.models.user_profile import UserProfile from src.prompts.course_generation import build_course_prompt, build_module_prompt from src.prompts.system import COURSE_SYSTEM_PROMPT from src.services.cohere_client import get_cohere_client from src.services.embedding import get_embedding_service -from src.knowledge.vectorstore import get_vectorstore logger = logging.getLogger(__name__) diff --git a/src/services/quiz_generator.py b/src/services/quiz_generator.py index 2309c6c..c1c71a2 100644 --- a/src/services/quiz_generator.py +++ b/src/services/quiz_generator.py @@ -3,12 +3,12 @@ import logging import uuid +from src.knowledge.vectorstore import get_vectorstore from src.models.quiz import GenerateQuizRequest, Quiz, QuizQuestion -from src.prompts.quiz_generation import build_quiz_prompt, build_question_from_content_prompt +from src.prompts.quiz_generation import build_question_from_content_prompt, build_quiz_prompt from src.prompts.system import QUIZ_SYSTEM_PROMPT from src.services.cohere_client import get_cohere_client from src.services.embedding import get_embedding_service -from src.knowledge.vectorstore import get_vectorstore logger = logging.getLogger(__name__)