""" LLM Chain implementation using Langchain for educational concept analysis """ from typing import Dict, Any, List from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.output_parsers import PydanticOutputParser from langchain.chains import LLMChain from pydantic import BaseModel, Field from config import OPENAI_API_KEY, OPENAI_MODEL # Define Pydantic models for structured output class Concept(BaseModel): """Model for a single concept""" id: str = Field(description="Unique identifier for the concept") name: str = Field(description="Name of the concept") description: str = Field(description="Brief description of the concept") difficulty: str = Field(description="Difficulty level: basic, intermediate, or advanced") class Relationship(BaseModel): """Model for relationship between concepts""" source: str = Field(description="Source concept ID") target: str = Field(description="Target concept ID") type: str = Field(description="Type of relationship: prerequisite or related") explanation: str = Field(description="Explanation of why this relationship exists") class ConceptMap(BaseModel): """Model for complete concept map""" main_concept: str = Field(description="Main concept being analyzed") sub_concepts: List[Concept] = Field(description="List of sub-concepts") relationships: List[Relationship] = Field(description="List of relationships between concepts") class Example(BaseModel): """Model for concept examples""" problem: str = Field(description="Example problem") solution: str = Field(description="Step-by-step solution") difficulty: str = Field(description="Difficulty level: Easy, Medium, or Hard") class Resource(BaseModel): """Model for learning resources""" type: str = Field(description="Type of resource (Video/Article/Interactive/Book)") title: str = Field(description="Resource title") description: str = Field(description="Resource description") link: str = Field(description="Optional resource link") class ConceptExplanation(BaseModel): """Model for detailed concept explanation""" explanation: str = Field(description="Detailed concept explanation") examples: List[Example] = Field(description="List of example problems and solutions") resources: List[Resource] = Field(description="List of learning resources") practice_questions: List[Example] = Field(description="List of practice questions") class EducationalLLMChain: """ Chain for processing educational concepts using LLM """ def __init__(self): """Initialize the LLM and parsers""" self.llm = ChatOpenAI( model=OPENAI_MODEL, temperature=0.1, openai_api_key=OPENAI_API_KEY ) # Initialize output parsers self.concept_parser = PydanticOutputParser(pydantic_object=ConceptMap) self.explanation_parser = PydanticOutputParser(pydantic_object=ConceptExplanation) # Create decomposition chain self.decomposition_chain = self._create_decomposition_chain() # Create explanation chain self.explanation_chain = self._create_explanation_chain() def _create_decomposition_chain(self) -> LLMChain: """ Create chain for concept decomposition Returns: LLMChain for decomposing concepts """ template = """You are an expert educational AI tutor. Analyze this question for a {grade} level student studying {subject}. Question: {question} Student Background: - Grade Level: {grade} - Subject: {subject} - Learning Needs: {learning_needs} Break down the concepts needed to understand this question into a knowledge graph. Consider the student's grade level and background knowledge. {format_instructions} """ prompt = ChatPromptTemplate.from_template( template=template, partial_variables={ "format_instructions": self.concept_parser.get_format_instructions() } ) return LLMChain(llm=self.llm, prompt=prompt) def _create_explanation_chain(self) -> LLMChain: """ Create chain for concept explanation Returns: LLMChain for explaining concepts """ template = """You are an expert educational tutor. Explain this concept for a {grade} level student studying {subject}: Concept: {concept_name} Description: {concept_description} Student Background: - Grade Level: {grade} - Subject: {subject} - Learning Needs: {learning_needs} Provide a detailed explanation, examples, resources, and practice questions. {format_instructions} """ prompt = ChatPromptTemplate.from_template( template=template, partial_variables={ "format_instructions": self.explanation_parser.get_format_instructions() } ) return LLMChain(llm=self.llm, prompt=prompt) async def decompose_concepts( self, question: str, grade: str, subject: str, learning_needs: str ) -> ConceptMap: """ Decompose a question into concepts Args: question: User's question grade: Educational grade level subject: Subject area learning_needs: Learning needs/goals Returns: Structured concept map """ response = await self.decomposition_chain.arun({ "question": question, "grade": grade, "subject": subject, "learning_needs": learning_needs }) return self.concept_parser.parse(response) async def explain_concept( self, concept_name: str, concept_description: str, grade: str, subject: str, learning_needs: str ) -> ConceptExplanation: """ Generate detailed concept explanation Args: concept_name: Name of concept to explain concept_description: Brief concept description grade: Educational grade level subject: Subject area learning_needs: Learning needs/goals Returns: Structured concept explanation """ response = await self.explanation_chain.arun({ "concept_name": concept_name, "concept_description": concept_description, "grade": grade, "subject": subject, "learning_needs": learning_needs }) return self.explanation_parser.parse(response)