Spaces:
Sleeping
Sleeping
Implement lesson practice agent and related functionality
Browse files- src/agents/base/flow.py +21 -11
- src/agents/base/func.py +15 -1
- src/agents/lesson_practice/flow.py +39 -0
- src/agents/lesson_practice/func.py +47 -0
- src/agents/lesson_practice/prompt.py +124 -0
- src/agents/lesson_practice/tools.py +16 -0
- src/agents/role_play/__pycache__/prompt.cpython-311.pyc +0 -0
- src/agents/role_play/__pycache__/scenarios.cpython-311.pyc +0 -0
- src/agents/role_play/prompt.py +5 -7
- src/apis/__pycache__/create_app.cpython-311.pyc +0 -0
- src/apis/create_app.py +2 -0
- src/apis/routes/lesson_route.py +42 -0
src/agents/base/flow.py
CHANGED
|
@@ -2,21 +2,31 @@ from langgraph.graph import StateGraph, START, END
|
|
| 2 |
from .func import State
|
| 3 |
from langgraph.graph.state import CompiledStateGraph
|
| 4 |
from langgraph.store.memory import InMemoryStore
|
|
|
|
|
|
|
| 5 |
class PrimaryChatBot:
|
| 6 |
def __init__(self):
|
| 7 |
-
|
| 8 |
|
| 9 |
@staticmethod
|
| 10 |
-
def
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
-
def node(self):
|
| 14 |
-
pass
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
def __call__(self) -> CompiledStateGraph:
|
| 20 |
-
|
| 21 |
-
self.
|
| 22 |
-
|
|
|
|
|
|
| 2 |
from .func import State
|
| 3 |
from langgraph.graph.state import CompiledStateGraph
|
| 4 |
from langgraph.store.memory import InMemoryStore
|
| 5 |
+
|
| 6 |
+
|
| 7 |
class PrimaryChatBot:
|
| 8 |
def __init__(self):
|
| 9 |
+
pass
|
| 10 |
|
| 11 |
@staticmethod
|
| 12 |
+
def should_continue(state: State):
|
| 13 |
+
messages = state["messages"]
|
| 14 |
+
last_message = messages[-1]
|
| 15 |
+
if not last_message.tool_calls:
|
| 16 |
+
return "end"
|
| 17 |
+
else:
|
| 18 |
+
return "continue"
|
| 19 |
|
| 20 |
+
def node(self, graph: StateGraph):
|
|
|
|
| 21 |
|
| 22 |
+
return graph
|
| 23 |
+
|
| 24 |
+
def edge(self, graph: StateGraph):
|
| 25 |
+
|
| 26 |
+
return graph
|
| 27 |
|
| 28 |
+
def __call__(self, checkpointer=InMemoryStore()) -> CompiledStateGraph:
|
| 29 |
+
graph = StateGraph(State)
|
| 30 |
+
graph: StateGraph = self.node(graph)
|
| 31 |
+
graph: StateGraph = self.edge(graph)
|
| 32 |
+
return graph.compile(checkpointer=checkpointer)
|
src/agents/base/func.py
CHANGED
|
@@ -1,4 +1,18 @@
|
|
| 1 |
from typing import TypedDict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
class State(TypedDict):
|
| 4 |
-
|
|
|
|
|
|
|
|
|
| 1 |
from typing import TypedDict
|
| 2 |
+
from langgraph.prebuilt import create_react_agent
|
| 3 |
+
|
| 4 |
+
from typing import (
|
| 5 |
+
Annotated,
|
| 6 |
+
Sequence,
|
| 7 |
+
TypedDict,
|
| 8 |
+
)
|
| 9 |
+
from langchain_core.messages import AnyMessage
|
| 10 |
+
from langgraph.graph.message import add_messages
|
| 11 |
+
import json
|
| 12 |
+
from src.config.llm import model
|
| 13 |
+
|
| 14 |
|
| 15 |
class State(TypedDict):
|
| 16 |
+
"""The state of the agent."""
|
| 17 |
+
|
| 18 |
+
messages: Annotated[Sequence[AnyMessage], add_messages]
|
src/agents/lesson_practice/flow.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langgraph.graph import StateGraph, START, END
|
| 2 |
+
from .func import State, agent, tool_node
|
| 3 |
+
from langgraph.graph.state import CompiledStateGraph
|
| 4 |
+
from langgraph.checkpoint.memory import InMemorySaver
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class LessonPracticeAgent:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
pass
|
| 10 |
+
|
| 11 |
+
@staticmethod
|
| 12 |
+
def should_continue(state: State):
|
| 13 |
+
messages = state["messages"]
|
| 14 |
+
last_message = messages[-1]
|
| 15 |
+
if not last_message.tool_calls:
|
| 16 |
+
return "end"
|
| 17 |
+
else:
|
| 18 |
+
return "continue"
|
| 19 |
+
|
| 20 |
+
def node(self, graph: StateGraph):
|
| 21 |
+
graph.add_node("agent", agent)
|
| 22 |
+
graph.add_node("tools", tool_node)
|
| 23 |
+
return graph
|
| 24 |
+
|
| 25 |
+
def edge(self, graph: StateGraph):
|
| 26 |
+
graph.add_edge(START, "agent")
|
| 27 |
+
graph.add_conditional_edges(
|
| 28 |
+
"agent", self.should_continue, {"end": END, "continue": "tools"}
|
| 29 |
+
)
|
| 30 |
+
return graph
|
| 31 |
+
|
| 32 |
+
def __call__(self, checkpointer=InMemorySaver()) -> CompiledStateGraph:
|
| 33 |
+
graph = StateGraph(State)
|
| 34 |
+
graph: StateGraph = self.node(graph)
|
| 35 |
+
graph: StateGraph = self.edge(graph)
|
| 36 |
+
return graph.compile(checkpointer=checkpointer)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
lesson_practice_agent = LessonPracticeAgent()
|
src/agents/lesson_practice/func.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import (
|
| 2 |
+
Annotated,
|
| 3 |
+
Sequence,
|
| 4 |
+
TypedDict,
|
| 5 |
+
)
|
| 6 |
+
from langchain_core.messages import ToolMessage, AnyMessage
|
| 7 |
+
from langgraph.graph.message import add_messages
|
| 8 |
+
import json
|
| 9 |
+
from .prompt import conversation_prompt
|
| 10 |
+
from src.config.llm import model
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class State(TypedDict):
|
| 14 |
+
"""The state of the agent."""
|
| 15 |
+
|
| 16 |
+
unit: str
|
| 17 |
+
vocabulary: list
|
| 18 |
+
key_structures: list
|
| 19 |
+
practice_questions: list
|
| 20 |
+
student_level: list
|
| 21 |
+
messages: Annotated[Sequence[AnyMessage], add_messages]
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
tools = []
|
| 25 |
+
|
| 26 |
+
tools_by_name = {tool.name: tool for tool in tools}
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
# Define our tool node
|
| 30 |
+
def tool_node(state: State):
|
| 31 |
+
outputs = []
|
| 32 |
+
for tool_call in state["messages"][-1].tool_calls:
|
| 33 |
+
tool_result = tools_by_name[tool_call["name"]].invoke(tool_call["args"])
|
| 34 |
+
outputs.append(
|
| 35 |
+
ToolMessage(
|
| 36 |
+
content=json.dumps(tool_result),
|
| 37 |
+
name=tool_call["name"],
|
| 38 |
+
tool_call_id=tool_call["id"],
|
| 39 |
+
)
|
| 40 |
+
)
|
| 41 |
+
return {"messages": outputs}
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
async def agent(state: State):
|
| 45 |
+
llm = conversation_prompt | model
|
| 46 |
+
response = await llm.ainvoke(state)
|
| 47 |
+
return {"messages": response}
|
src/agents/lesson_practice/prompt.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.prompts import ChatPromptTemplate
|
| 2 |
+
from src.config.llm import model
|
| 3 |
+
|
| 4 |
+
conversation_prompt = ChatPromptTemplate.from_messages(
|
| 5 |
+
[
|
| 6 |
+
(
|
| 7 |
+
"system",
|
| 8 |
+
"""# English Speaking Practice Agent - Universal Prompt
|
| 9 |
+
|
| 10 |
+
## Role & Objective
|
| 11 |
+
You are an experienced English teacher having a natural conversation with Vietnamese students. Your goal is to help them practice speaking English through engaging dialogue, subtly incorporating their recent learning while adapting to their responses and providing gentle guidance when needed.
|
| 12 |
+
|
| 13 |
+
## Input Data Format
|
| 14 |
+
INSERT LESSON DATA HERE:
|
| 15 |
+
```
|
| 16 |
+
UNIT: {unit}
|
| 17 |
+
VOCABULARY: {vocabulary}
|
| 18 |
+
KEY STRUCTURES: {key_structures}
|
| 19 |
+
PRACTICE QUESTIONS: {practice_questions}
|
| 20 |
+
STUDENT LEVEL: {student_level}
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
## Core Teaching Conversation Principles
|
| 24 |
+
|
| 25 |
+
### 1. Adaptive Question Flow
|
| 26 |
+
- Use CONVERSATION STARTERS as natural talking points, not rigid questions
|
| 27 |
+
- Expand organically based on student's interests and responses
|
| 28 |
+
- Create 2-3 meaningful follow-ups that explore their answers deeper
|
| 29 |
+
- Seamlessly weave in new topics when conversation naturally flows there
|
| 30 |
+
|
| 31 |
+
### 2. Natural Teaching Moments
|
| 32 |
+
- Notice opportunities to teach vocabulary and patterns from the context data
|
| 33 |
+
- Introduce new language organically when student shows readiness
|
| 34 |
+
- Connect new concepts to what student already shared
|
| 35 |
+
- Let conversation flow naturally rather than forcing topic changes
|
| 36 |
+
|
| 37 |
+
### 3. Supportive Guidance When Stuck
|
| 38 |
+
**Progressive teaching approach:**
|
| 39 |
+
- **Notice confusion** and offer one helpful hint or explanation
|
| 40 |
+
- **Ask what type of help they need:** vocabulary support or sentence building help
|
| 41 |
+
- **Provide just enough support** to get them moving forward
|
| 42 |
+
- **Always check understanding** before proceeding
|
| 43 |
+
|
| 44 |
+
### 4. Gentle Error Correction
|
| 45 |
+
- **Address one main issue** without overwhelming them
|
| 46 |
+
- **Show correct version** with brief, friendly explanation
|
| 47 |
+
- **Encourage them** to try using the correction again
|
| 48 |
+
|
| 49 |
+
### 5. Encouraging Success
|
| 50 |
+
- **Celebrate their efforts** and connect to something interesting they shared
|
| 51 |
+
- **Explore their response** with follow-up questions about their experiences
|
| 52 |
+
|
| 53 |
+
### 6. Handling Curiosity Tangents
|
| 54 |
+
**When student brings up interesting topics:**
|
| 55 |
+
1. **Engage briefly** with genuine interest
|
| 56 |
+
2. **Check their preference** about exploring the topic further or changing direction
|
| 57 |
+
3. **Follow their lead** based on their response
|
| 58 |
+
|
| 59 |
+
### 7. Sensitive Response Handling
|
| 60 |
+
- **Stay warm and understanding** when student seems uncomfortable with a topic
|
| 61 |
+
- **Redirect thoughtfully** to topics they might enjoy more
|
| 62 |
+
|
| 63 |
+
### 8. Advanced Learning Opportunities (B2+)
|
| 64 |
+
- **Naturally introduce sophisticated alternatives** when student shows strong responses
|
| 65 |
+
- **Offer language upgrades** with more advanced vocabulary or structures
|
| 66 |
+
|
| 67 |
+
### 9. Natural Conversation Closure
|
| 68 |
+
- **Acknowledge the great conversation** you've had together
|
| 69 |
+
- **Suggest continued practice** with role-play scenarios or dialogue reading
|
| 70 |
+
|
| 71 |
+
## Teaching Approach
|
| 72 |
+
|
| 73 |
+
### Conversation Initiation
|
| 74 |
+
Start conversations naturally and warmly, using CONVERSATION STARTERS as organic talking points rather than formal questions.
|
| 75 |
+
|
| 76 |
+
### Natural Teaching Flow
|
| 77 |
+
- **Student-centered:** Follow their interests and energy level
|
| 78 |
+
- **Vocabulary integration:** Weave in VOCABULARY TO PRACTICE when opportunities naturally arise
|
| 79 |
+
- **Pattern practice:** Subtly reinforce KEY LANGUAGE PATTERNS through your responses and gentle corrections
|
| 80 |
+
- **Adaptive questioning:** Use their responses to create meaningful follow-up conversations
|
| 81 |
+
|
| 82 |
+
### Teaching Style
|
| 83 |
+
- **Encouraging and patient:** Create a safe space for making mistakes and learning
|
| 84 |
+
- **Genuinely curious:** Show real interest in what student shares
|
| 85 |
+
- **Adaptive support:** Provide just the right amount of help - not too much, not too little
|
| 86 |
+
- **Natural educator:** Teach through conversation rather than formal instruction
|
| 87 |
+
|
| 88 |
+
## Technical Implementation
|
| 89 |
+
|
| 90 |
+
### Natural Language Teaching
|
| 91 |
+
- **Primary language:** English conversation with natural teacher-student interaction
|
| 92 |
+
- **Supportive explanations:** Brief Vietnamese only when student is genuinely stuck
|
| 93 |
+
- **Pronunciation help:** Reference IPA from vocabulary data when pronunciation issues arise
|
| 94 |
+
|
| 95 |
+
### Intelligent Adaptation
|
| 96 |
+
- **Content responsiveness:** Naturally incorporate topic focus and vocabulary based on conversation flow
|
| 97 |
+
- **Level sensitivity:** Adjust language complexity and support based on student responses
|
| 98 |
+
- **Interest-driven:** Follow student's curiosity and engagement levels
|
| 99 |
+
|
| 100 |
+
### Quality Teaching Standards
|
| 101 |
+
- **Conversation coverage:** Naturally touch on topics from CONVERSATION STARTERS during the chat
|
| 102 |
+
- **Principle consistency:** Maintain all 9 teaching principles throughout interaction
|
| 103 |
+
- **Organic progression:** Let conversation develop naturally while ensuring educational value
|
| 104 |
+
|
| 105 |
+
## Response Guidelines
|
| 106 |
+
- **Simple responses: Under 15 words** - keep basic answers short and conversational
|
| 107 |
+
- **Explanations: 15-30 words** - provide brief explanation then create follow-up question for deeper exploration
|
| 108 |
+
- **Detailed explanations: 30-40 words maximum** - offer focused detail then ask if they want to know more
|
| 109 |
+
- **Never exceed 40 words** in a single response - always break into smaller, digestible pieces
|
| 110 |
+
- **Always include engaging questions** to discover student's interests and comfort level
|
| 111 |
+
- **Student-driven depth** through open-ended questions about their thoughts and experiences
|
| 112 |
+
- **Progressive teaching:** Start simple, offer complexity only when student shows readiness
|
| 113 |
+
- **Natural conversation flow** using warm, encouraging teacher language
|
| 114 |
+
- Use CONVERSATION STARTERS as natural talking points throughout the chat
|
| 115 |
+
- Weave VOCABULARY TO PRACTICE and KEY LANGUAGE PATTERNS into natural conversation
|
| 116 |
+
- Maintain warm, encouraging teaching presence while keeping conversation engaging
|
| 117 |
+
- Always prioritize student comfort and learning pace while building speaking confidence
|
| 118 |
+
""",
|
| 119 |
+
),
|
| 120 |
+
("placeholder", "{messages}"),
|
| 121 |
+
]
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
conversation_chain = conversation_prompt | model
|
src/agents/lesson_practice/tools.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.tools import tool
|
| 2 |
+
from loguru import logger
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
@tool
|
| 6 |
+
def function_name(
|
| 7 |
+
input: str,
|
| 8 |
+
) -> str:
|
| 9 |
+
"""
|
| 10 |
+
Mô tả chức năng của hàm này.
|
| 11 |
+
"""
|
| 12 |
+
logger.info(f"Received input: {input}")
|
| 13 |
+
# Thực hiện các thao tác cần thiết với input
|
| 14 |
+
result = f"Processed: {input}"
|
| 15 |
+
logger.info(f"Returning result: {result}")
|
| 16 |
+
return result
|
src/agents/role_play/__pycache__/prompt.cpython-311.pyc
CHANGED
|
Binary files a/src/agents/role_play/__pycache__/prompt.cpython-311.pyc and b/src/agents/role_play/__pycache__/prompt.cpython-311.pyc differ
|
|
|
src/agents/role_play/__pycache__/scenarios.cpython-311.pyc
CHANGED
|
Binary files a/src/agents/role_play/__pycache__/scenarios.cpython-311.pyc and b/src/agents/role_play/__pycache__/scenarios.cpython-311.pyc differ
|
|
|
src/agents/role_play/prompt.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
| 1 |
-
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
## About Wise Tutor:
|
| 8 |
-
If asked about your name or identity, respond warmly: "I'm part of Wise Tutor! I'm here to help you practice English through fun conversations. Think of me as your friendly conversation partner!"
|
| 9 |
|
| 10 |
## CRITICAL LANGUAGE RULE:
|
| 11 |
**IF USER SPEAKS ANY LANGUAGE OTHER THAN ENGLISH → IMMEDIATELY HAND OFF TO GUIDING AGENT**
|
|
@@ -221,4 +219,4 @@ Remember:
|
|
| 221 |
- **Only use Vietnamese when truly needed for guidance**
|
| 222 |
- **Handoff to Roleplay when user shows English conversation readiness**
|
| 223 |
- Focus on preparing them for successful English conversation
|
| 224 |
-
"""
|
|
|
|
| 1 |
+
roleplay_prompt = """# Role: Roleplay Partner - Part of English AI Learning System
|
| 2 |
|
| 3 |
+
You are part of Tutor, a friendly English learning companion. You're the roleplay specialist who creates natural, authentic conversations with learners.
|
| 4 |
|
| 5 |
+
## About you
|
| 6 |
+
If asked for your name or role, tell the user who you are {your_role} to make users feel like they are in a real conversation.
|
|
|
|
|
|
|
| 7 |
|
| 8 |
## CRITICAL LANGUAGE RULE:
|
| 9 |
**IF USER SPEAKS ANY LANGUAGE OTHER THAN ENGLISH → IMMEDIATELY HAND OFF TO GUIDING AGENT**
|
|
|
|
| 219 |
- **Only use Vietnamese when truly needed for guidance**
|
| 220 |
- **Handoff to Roleplay when user shows English conversation readiness**
|
| 221 |
- Focus on preparing them for successful English conversation
|
| 222 |
+
"""
|
src/apis/__pycache__/create_app.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/__pycache__/create_app.cpython-311.pyc and b/src/apis/__pycache__/create_app.cpython-311.pyc differ
|
|
|
src/apis/create_app.py
CHANGED
|
@@ -2,10 +2,12 @@ from fastapi import FastAPI, APIRouter
|
|
| 2 |
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
from src.apis.routes.user_route import router as router_user
|
| 4 |
from src.apis.routes.chat_route import router as router_chat
|
|
|
|
| 5 |
|
| 6 |
api_router = APIRouter(prefix="/api")
|
| 7 |
api_router.include_router(router_user)
|
| 8 |
api_router.include_router(router_chat)
|
|
|
|
| 9 |
|
| 10 |
|
| 11 |
def create_app():
|
|
|
|
| 2 |
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
from src.apis.routes.user_route import router as router_user
|
| 4 |
from src.apis.routes.chat_route import router as router_chat
|
| 5 |
+
from src.apis.routes.lesson_route import router as router_lesson
|
| 6 |
|
| 7 |
api_router = APIRouter(prefix="/api")
|
| 8 |
api_router.include_router(router_user)
|
| 9 |
api_router.include_router(router_chat)
|
| 10 |
+
api_router.include_router(router_lesson)
|
| 11 |
|
| 12 |
|
| 13 |
def create_app():
|
src/apis/routes/lesson_route.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, status, Depends, BackgroundTasks, HTTPException
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
from src.utils.logger import logger
|
| 4 |
+
from pydantic import BaseModel, Field
|
| 5 |
+
from typing import List, Dict, Any, Optional
|
| 6 |
+
from src.agents.lesson_practice.flow import lesson_practice_agent
|
| 7 |
+
import json
|
| 8 |
+
import os
|
| 9 |
+
import uuid
|
| 10 |
+
from datetime import datetime
|
| 11 |
+
|
| 12 |
+
router = APIRouter(prefix="/lesson", tags=["AI"])
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class LessonPracticeRequest(BaseModel):
|
| 16 |
+
unit: str = Field(..., description="Unit of the lesson")
|
| 17 |
+
vocabulary: list = Field(..., description="Vocabulary for the lesson")
|
| 18 |
+
key_structures: list = Field(..., description="Key structures for the lesson")
|
| 19 |
+
practice_questions: list = Field(
|
| 20 |
+
..., description="Practice questions for the lesson"
|
| 21 |
+
)
|
| 22 |
+
student_level: str = Field("beginner", description="Student's level of English")
|
| 23 |
+
query: str = Field(..., description="User query for the lesson")
|
| 24 |
+
session_id: str = Field(..., description="Session ID for the lesson")
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@router.post("/chat")
|
| 28 |
+
async def chat(request: LessonPracticeRequest):
|
| 29 |
+
response = await lesson_practice_agent().ainvoke(
|
| 30 |
+
{
|
| 31 |
+
"unit": request.unit,
|
| 32 |
+
"vocabulary": request.vocabulary,
|
| 33 |
+
"key_structures": request.key_structures,
|
| 34 |
+
"practice_questions": request.practice_questions,
|
| 35 |
+
"student_level": request.student_level,
|
| 36 |
+
"messages": [request.query],
|
| 37 |
+
},
|
| 38 |
+
{"configurable": {"thread_id": request.session_id}},
|
| 39 |
+
)
|
| 40 |
+
return JSONResponse(
|
| 41 |
+
content=response["messages"][-1].content, status_code=status.HTTP_200_OK
|
| 42 |
+
)
|