Upload 78 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitignore +1 -0
- Dockerfile +13 -0
- README.md +4 -4
- agent.py +173 -0
- app.py +12 -0
- requirements.txt +14 -0
- src/.DS_Store +0 -0
- src/Untitled.ipynb +51 -0
- src/__pycache__/__init__.cpython-311.pyc +0 -0
- src/__pycache__/app.cpython-311.pyc +0 -0
- src/__pycache__/state.cpython-311.pyc +0 -0
- src/agents/.DS_Store +0 -0
- src/agents/base/flow.py +22 -0
- src/agents/base/func.py +4 -0
- src/agents/base/prompt.py +14 -0
- src/agents/base/tools.py +16 -0
- src/agents/role_play/__pycache__/func.cpython-311.pyc +0 -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/flow.py +24 -0
- src/agents/role_play/func.py +55 -0
- src/agents/role_play/prompt.py +187 -0
- src/agents/role_play/scenarios.py +195 -0
- src/agents/role_play/tools.py +16 -0
- src/agents/tools/__pycache__/crawl.cpython-311.pyc +0 -0
- src/agents/tools/crawl.py +24 -0
- src/apis/.DS_Store +0 -0
- src/apis/__pycache__/__init__.cpython-311.pyc +0 -0
- src/apis/__pycache__/create_app.cpython-311.pyc +0 -0
- src/apis/config/__pycache__/firebase_config.cpython-311.pyc +0 -0
- src/apis/create_app.py +22 -0
- src/apis/interfaces/.DS_Store +0 -0
- src/apis/interfaces/__pycache__/api_interface.cpython-311.pyc +0 -0
- src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc +0 -0
- src/apis/interfaces/api_interface.py +5 -0
- src/apis/interfaces/auth_interface.py +2 -0
- src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc +0 -0
- src/apis/middlewares/auth_middleware.py +0 -0
- src/apis/models/.DS_Store +0 -0
- src/apis/models/BaseModel.py +17 -0
- src/apis/models/__pycache__/BaseModel.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/destination_models.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/hotel_models.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/post_models.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/schedule_models.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/user_models.cpython-311.pyc +0 -0
- src/apis/models/user_models.py +0 -0
- src/apis/providers/.DS_Store +0 -0
- src/apis/providers/__pycache__/__init__.cpython-311.pyc +0 -0
- src/apis/providers/__pycache__/firebase_provider.cpython-311.pyc +0 -0
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.env
|
Dockerfile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
RUN useradd -m -u 1000 user
|
| 4 |
+
USER user
|
| 5 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 6 |
+
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 10 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY --chown=user . /app
|
| 13 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
|
README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
| 8 |
---
|
|
|
|
| 1 |
---
|
| 2 |
+
title: English Roleplay
|
| 3 |
+
emoji: 🐨
|
| 4 |
+
colorFrom: pink
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
| 8 |
---
|
agent.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
|
| 3 |
+
load_dotenv()
|
| 4 |
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 5 |
+
from langgraph.checkpoint.memory import InMemorySaver
|
| 6 |
+
from langgraph.prebuilt import create_react_agent
|
| 7 |
+
from langgraph_swarm import create_handoff_tool, create_swarm
|
| 8 |
+
|
| 9 |
+
model = ChatGoogleGenerativeAI(
|
| 10 |
+
model="gemini-2.5-flash",
|
| 11 |
+
temperature=0,
|
| 12 |
+
max_tokens=None,
|
| 13 |
+
timeout=None,
|
| 14 |
+
max_retries=2,
|
| 15 |
+
# other params...
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def add(a: int, b: int) -> int:
|
| 20 |
+
"""Add two numbers"""
|
| 21 |
+
return a + b
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
transfer_to_language_helper = create_handoff_tool(
|
| 25 |
+
agent_name="language_helper",
|
| 26 |
+
description="Transfer to language helper when user needs gentle grammar/vocabulary support",
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
transfer_to_character_agent = create_handoff_tool(
|
| 30 |
+
agent_name="character_agent",
|
| 31 |
+
description="Transfer to main conversation character for natural chat",
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
transfer_to_orchestrator = create_handoff_tool(
|
| 35 |
+
agent_name="orchestrator",
|
| 36 |
+
description="Transfer to orchestrator for conversation flow management",
|
| 37 |
+
)
|
| 38 |
+
# ========================= AGENT PROMPTS =========================
|
| 39 |
+
|
| 40 |
+
CHARACTER_AGENT_PROMPT = """
|
| 41 |
+
You are a friendly, patient conversation partner helping someone practice English.
|
| 42 |
+
|
| 43 |
+
PERSONALITY:
|
| 44 |
+
- Warm, encouraging, and genuinely interested
|
| 45 |
+
- Patient with language learners
|
| 46 |
+
- Natural conversationalist, not a formal teacher
|
| 47 |
+
- Use Elementary English (A1-A2 level) naturally
|
| 48 |
+
|
| 49 |
+
CONVERSATION APPROACH:
|
| 50 |
+
- Always respond warmly to whatever the user says
|
| 51 |
+
- Show genuine interest in their thoughts and experiences
|
| 52 |
+
- Use simple, clear language naturally
|
| 53 |
+
- Ask engaging follow-up questions
|
| 54 |
+
- If they go off-topic, engage naturally first
|
| 55 |
+
|
| 56 |
+
CURRENT CONVERSATION THEME: {theme}
|
| 57 |
+
- Gently weave theme-related topics when it feels natural
|
| 58 |
+
- Don't force the theme if user wants to talk about other things
|
| 59 |
+
- Let conversation flow organically
|
| 60 |
+
|
| 61 |
+
LANGUAGE LEVEL GUIDELINES:
|
| 62 |
+
- Use common vocabulary (avoid complex words)
|
| 63 |
+
- Simple sentence structures
|
| 64 |
+
- Clear pronunciation cues in text
|
| 65 |
+
- Encouraging tone
|
| 66 |
+
|
| 67 |
+
EXAMPLES:
|
| 68 |
+
User: "I like cats" → "Cats are wonderful! Do you have a cat? I think they're so independent and cute."
|
| 69 |
+
User: "I'm tired today" → "Oh no! Long day? Sometimes when I'm tired, I just want to relax. What helps you feel better?"
|
| 70 |
+
|
| 71 |
+
Remember: You're their conversation partner, not their teacher. Make them feel comfortable and want to keep talking!
|
| 72 |
+
"""
|
| 73 |
+
|
| 74 |
+
LANGUAGE_HELPER_PROMPT = """
|
| 75 |
+
You are a gentle language helper - like helping a friend with English in a very supportive way.
|
| 76 |
+
|
| 77 |
+
YOUR APPROACH:
|
| 78 |
+
- Help only when there are major communication barriers
|
| 79 |
+
- Keep corrections brief and encouraging
|
| 80 |
+
- Immediately return to natural conversation
|
| 81 |
+
- Never make them feel bad about mistakes
|
| 82 |
+
- Focus on communication, not perfection
|
| 83 |
+
|
| 84 |
+
HELPING STYLE:
|
| 85 |
+
1. If meaning is clear despite small errors → ignore errors, continue conversation
|
| 86 |
+
2. If meaning is unclear → offer gentle help:
|
| 87 |
+
- "I think you mean: [corrected version]?"
|
| 88 |
+
- "Oh, you can say: [natural way]"
|
| 89 |
+
- Then immediately continue the conversation
|
| 90 |
+
|
| 91 |
+
3. If they struggle with words → offer quick support:
|
| 92 |
+
- "The word you might be looking for is..."
|
| 93 |
+
- "You could say..."
|
| 94 |
+
|
| 95 |
+
EXAMPLES:
|
| 96 |
+
User: "I go shop yesterday" → "Oh, you went shopping yesterday? That sounds fun! What did you buy?"
|
| 97 |
+
User: "I want... um... the thing for coffee" → "Oh, do you mean a coffee cup? Or maybe a coffee maker?"
|
| 98 |
+
|
| 99 |
+
Keep it conversational and supportive. Your goal is to help communication flow, not to teach grammar lessons.
|
| 100 |
+
"""
|
| 101 |
+
|
| 102 |
+
ORCHESTRATOR_PROMPT = """
|
| 103 |
+
You are a conversation flow manager for an English practice chat system.
|
| 104 |
+
|
| 105 |
+
YOUR ROLE:
|
| 106 |
+
- Monitor conversation quality and user engagement
|
| 107 |
+
- Decide when language help is truly needed
|
| 108 |
+
- Keep conversations natural and flowing
|
| 109 |
+
- Track user preferences (topic-focused vs free-talk)
|
| 110 |
+
|
| 111 |
+
DECISION MAKING:
|
| 112 |
+
- Only send to language_helper if there's a real communication barrier
|
| 113 |
+
- Let character_agent handle 90% of interactions
|
| 114 |
+
- Prioritize user comfort and engagement over strict language correction
|
| 115 |
+
|
| 116 |
+
ANALYSIS TOOLS: Use analyze_language_need to assess if help is needed
|
| 117 |
+
|
| 118 |
+
ROUTING PRINCIPLES:
|
| 119 |
+
- Default to character_agent for natural conversation
|
| 120 |
+
- Transfer to language_helper only for major communication issues
|
| 121 |
+
- Always prioritize conversation flow over language perfection
|
| 122 |
+
|
| 123 |
+
Current conversation theme: {theme}
|
| 124 |
+
User engagement level: {engagement}
|
| 125 |
+
"""
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
character_agent = create_react_agent(
|
| 129 |
+
model=model,
|
| 130 |
+
tools=[
|
| 131 |
+
transfer_to_language_helper,
|
| 132 |
+
transfer_to_orchestrator,
|
| 133 |
+
],
|
| 134 |
+
prompt=CHARACTER_AGENT_PROMPT.format(theme="technical interview"),
|
| 135 |
+
name="character_agent",
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
# Create Language Helper (Gentle support)
|
| 139 |
+
language_helper = create_react_agent(
|
| 140 |
+
model=model,
|
| 141 |
+
tools=[transfer_to_character_agent, transfer_to_orchestrator],
|
| 142 |
+
prompt=LANGUAGE_HELPER_PROMPT,
|
| 143 |
+
name="language_helper",
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
# Create Orchestrator (Flow manager)
|
| 147 |
+
orchestrator = create_react_agent(
|
| 148 |
+
model=model,
|
| 149 |
+
tools=[
|
| 150 |
+
transfer_to_character_agent,
|
| 151 |
+
transfer_to_language_helper,
|
| 152 |
+
],
|
| 153 |
+
prompt=ORCHESTRATOR_PROMPT,
|
| 154 |
+
name="orchestrator",
|
| 155 |
+
)
|
| 156 |
+
checkpointer = InMemorySaver()
|
| 157 |
+
workflow = create_swarm(
|
| 158 |
+
agents=[character_agent, language_helper, orchestrator],
|
| 159 |
+
default_active_agent="character_agent", # Start with friendly conversation
|
| 160 |
+
).compile(checkpointer=checkpointer)
|
| 161 |
+
|
| 162 |
+
config = {"configurable": {"thread_id": "1"}}
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
while True:
|
| 166 |
+
user_input = input("You: ")
|
| 167 |
+
if user_input.lower() == "exit":
|
| 168 |
+
break
|
| 169 |
+
response = workflow.invoke(
|
| 170 |
+
{"messages": [{"role": "user", "content": user_input}]},
|
| 171 |
+
config,
|
| 172 |
+
)
|
| 173 |
+
print("Bot:", response["messages"][-1].content)
|
app.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
|
| 3 |
+
load_dotenv()
|
| 4 |
+
from src.apis.create_app import create_app, api_router
|
| 5 |
+
import uvicorn
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
app = create_app()
|
| 9 |
+
|
| 10 |
+
app.include_router(api_router)
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=False)
|
requirements.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
python-dateutil
|
| 4 |
+
pandas
|
| 5 |
+
openpyxl
|
| 6 |
+
redis
|
| 7 |
+
bs4
|
| 8 |
+
pytz
|
| 9 |
+
langgraph
|
| 10 |
+
langchain
|
| 11 |
+
langgraph-swarm
|
| 12 |
+
langchain-google-genai
|
| 13 |
+
python-dotenv
|
| 14 |
+
loguru
|
src/.DS_Store
ADDED
|
Binary file (8.2 kB). View file
|
|
|
src/Untitled.ipynb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 1,
|
| 6 |
+
"id": "00ef7a54-9c8a-4235-82d1-9df1ac5f2967",
|
| 7 |
+
"metadata": {},
|
| 8 |
+
"outputs": [
|
| 9 |
+
{
|
| 10 |
+
"name": "stdout",
|
| 11 |
+
"output_type": "stream",
|
| 12 |
+
"text": [
|
| 13 |
+
"hello\n"
|
| 14 |
+
]
|
| 15 |
+
}
|
| 16 |
+
],
|
| 17 |
+
"source": [
|
| 18 |
+
"print('hello')"
|
| 19 |
+
]
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"cell_type": "code",
|
| 23 |
+
"execution_count": null,
|
| 24 |
+
"id": "d2e19d62-d6ba-4cb7-ac8c-b965cf65b2d7",
|
| 25 |
+
"metadata": {},
|
| 26 |
+
"outputs": [],
|
| 27 |
+
"source": []
|
| 28 |
+
}
|
| 29 |
+
],
|
| 30 |
+
"metadata": {
|
| 31 |
+
"kernelspec": {
|
| 32 |
+
"display_name": "Python 3 (ipykernel)",
|
| 33 |
+
"language": "python",
|
| 34 |
+
"name": "python3"
|
| 35 |
+
},
|
| 36 |
+
"language_info": {
|
| 37 |
+
"codemirror_mode": {
|
| 38 |
+
"name": "ipython",
|
| 39 |
+
"version": 3
|
| 40 |
+
},
|
| 41 |
+
"file_extension": ".py",
|
| 42 |
+
"mimetype": "text/x-python",
|
| 43 |
+
"name": "python",
|
| 44 |
+
"nbconvert_exporter": "python",
|
| 45 |
+
"pygments_lexer": "ipython3",
|
| 46 |
+
"version": "3.11.9"
|
| 47 |
+
}
|
| 48 |
+
},
|
| 49 |
+
"nbformat": 4,
|
| 50 |
+
"nbformat_minor": 5
|
| 51 |
+
}
|
src/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (221 Bytes). View file
|
|
|
src/__pycache__/app.cpython-311.pyc
ADDED
|
Binary file (958 Bytes). View file
|
|
|
src/__pycache__/state.cpython-311.pyc
ADDED
|
Binary file (763 Bytes). View file
|
|
|
src/agents/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
src/agents/base/flow.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
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 |
+
self.builder = StateGraph(State)
|
| 8 |
+
|
| 9 |
+
@staticmethod
|
| 10 |
+
def routing(state: State):
|
| 11 |
+
pass
|
| 12 |
+
|
| 13 |
+
def node(self):
|
| 14 |
+
pass
|
| 15 |
+
|
| 16 |
+
def edge(self):
|
| 17 |
+
pass
|
| 18 |
+
|
| 19 |
+
def __call__(self) -> CompiledStateGraph:
|
| 20 |
+
self.node()
|
| 21 |
+
self.edge()
|
| 22 |
+
return self.builder.compile(checkpointer=InMemoryStore())
|
src/agents/base/func.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import TypedDict
|
| 2 |
+
|
| 3 |
+
class State(TypedDict):
|
| 4 |
+
pass
|
src/agents/base/prompt.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.prompts import ChatPromptTemplate
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
base_prompt = ChatPromptTemplate.from_messages(
|
| 5 |
+
[
|
| 6 |
+
(
|
| 7 |
+
"system",
|
| 8 |
+
"""Vai trò
|
| 9 |
+
|
| 10 |
+
""",
|
| 11 |
+
),
|
| 12 |
+
("placeholder", "{messages}"),
|
| 13 |
+
]
|
| 14 |
+
)
|
src/agents/base/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__/func.cpython-311.pyc
ADDED
|
Binary file (2.33 kB). View file
|
|
|
src/agents/role_play/__pycache__/prompt.cpython-311.pyc
ADDED
|
Binary file (7.56 kB). View file
|
|
|
src/agents/role_play/__pycache__/scenarios.cpython-311.pyc
ADDED
|
Binary file (6.36 kB). View file
|
|
|
src/agents/role_play/flow.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
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 |
+
|
| 6 |
+
|
| 7 |
+
class PrimaryChatBot:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
self.builder = StateGraph(State)
|
| 10 |
+
|
| 11 |
+
@staticmethod
|
| 12 |
+
def routing(state: State):
|
| 13 |
+
pass
|
| 14 |
+
|
| 15 |
+
def node(self):
|
| 16 |
+
pass
|
| 17 |
+
|
| 18 |
+
def edge(self):
|
| 19 |
+
pass
|
| 20 |
+
|
| 21 |
+
def __call__(self) -> CompiledStateGraph:
|
| 22 |
+
self.node()
|
| 23 |
+
self.edge()
|
| 24 |
+
return self.builder.compile(checkpointer=InMemoryStore())
|
src/agents/role_play/func.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import TypedDict
|
| 2 |
+
from src.config.llm import model
|
| 3 |
+
from langgraph.checkpoint.memory import InMemorySaver
|
| 4 |
+
from langgraph.prebuilt import create_react_agent
|
| 5 |
+
from langgraph_swarm import create_handoff_tool, create_swarm
|
| 6 |
+
from .prompt import roleplay_prompt, guiding_prompt
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class State(TypedDict):
|
| 10 |
+
pass
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def create_agents(scenario, checkpointer=InMemorySaver()):
|
| 14 |
+
|
| 15 |
+
roleplay_agent = create_react_agent(
|
| 16 |
+
model,
|
| 17 |
+
[
|
| 18 |
+
create_handoff_tool(
|
| 19 |
+
agent_name="Guiding Agent",
|
| 20 |
+
description="Hand off to Guiding Agent when user shows signs of needing help, guidance, or struggles with communication",
|
| 21 |
+
),
|
| 22 |
+
],
|
| 23 |
+
prompt=roleplay_prompt.format(
|
| 24 |
+
scenario_title=scenario["scenario_title"],
|
| 25 |
+
scenario_description=scenario["scenario_description"],
|
| 26 |
+
scenario_context=scenario["scenario_context"],
|
| 27 |
+
your_role=scenario["your_role"],
|
| 28 |
+
key_vocabulary=scenario["key_vocabulary"],
|
| 29 |
+
),
|
| 30 |
+
name="Roleplay Agent",
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
guiding_agent = create_react_agent(
|
| 34 |
+
model,
|
| 35 |
+
[
|
| 36 |
+
create_handoff_tool(
|
| 37 |
+
agent_name="Roleplay Agent",
|
| 38 |
+
description="Hand off back to Roleplay Agent when user is ready for scenario practice and shows improved confidence",
|
| 39 |
+
),
|
| 40 |
+
],
|
| 41 |
+
prompt=guiding_prompt.format(
|
| 42 |
+
scenario_title=scenario["scenario_title"],
|
| 43 |
+
scenario_description=scenario["scenario_description"],
|
| 44 |
+
scenario_context=scenario["scenario_context"],
|
| 45 |
+
your_role=scenario["your_role"],
|
| 46 |
+
key_vocabulary=scenario["key_vocabulary"],
|
| 47 |
+
),
|
| 48 |
+
name="Guiding Agent",
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
workflow = create_swarm(
|
| 52 |
+
[roleplay_agent, guiding_agent], default_active_agent="Roleplay Agent"
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
return workflow.compile(checkpointer)
|
src/agents/role_play/prompt.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_core.prompts import ChatPromptTemplate
|
| 2 |
+
|
| 3 |
+
roleplay_prompt = """# Role: Roleplay Partner - Part of the Wise Tutor System
|
| 4 |
+
|
| 5 |
+
You are part of Wise Tutor, a friendly English learning companion. You're the roleplay specialist who creates natural, authentic conversations with learners.
|
| 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**
|
| 12 |
+
This is an English learning experience. Users need to practice English for roleplay.
|
| 13 |
+
|
| 14 |
+
## Current Scenario Context:
|
| 15 |
+
{scenario_title}: {scenario_description}
|
| 16 |
+
Setting: {scenario_context}
|
| 17 |
+
Your role: {your_role}
|
| 18 |
+
Key vocabulary: {key_vocabulary}
|
| 19 |
+
|
| 20 |
+
## Your Mission:
|
| 21 |
+
- Be a real, authentic person in your role ({your_role})
|
| 22 |
+
- Have genuine conversations, not rehearsed interactions
|
| 23 |
+
- React naturally to what users say - show surprise, interest, concern
|
| 24 |
+
- Make the experience feel like talking to a real person
|
| 25 |
+
- ONLY engage in roleplay when user speaks English
|
| 26 |
+
|
| 27 |
+
## Language Detection Protocol:
|
| 28 |
+
### If User Uses Non-English:
|
| 29 |
+
- **DO NOT respond in their language**
|
| 30 |
+
- **DO NOT continue roleplay**
|
| 31 |
+
- **IMMEDIATELY hand off to Guiding Agent**
|
| 32 |
+
|
| 33 |
+
### If User Uses English:
|
| 34 |
+
- Continue with natural roleplay as described below
|
| 35 |
+
|
| 36 |
+
## Natural Conversation Principles:
|
| 37 |
+
|
| 38 |
+
### Be Authentically Human:
|
| 39 |
+
- Show genuine emotions and reactions
|
| 40 |
+
- Use conversational language, not formal scripts
|
| 41 |
+
- Respond to the unexpected - be flexible
|
| 42 |
+
- Have your own personality as the character
|
| 43 |
+
- Make small talk when appropriate
|
| 44 |
+
|
| 45 |
+
### Stay True to Your Role:
|
| 46 |
+
- Embody the character realistically ({your_role})
|
| 47 |
+
- Use language and knowledge appropriate to your role
|
| 48 |
+
- Have realistic limitations and expertise
|
| 49 |
+
- React as this person would in real situations
|
| 50 |
+
|
| 51 |
+
### Create Real Interactions:
|
| 52 |
+
- Build genuine rapport with the user
|
| 53 |
+
- Remember details they share and reference them later
|
| 54 |
+
- Ask follow-up questions that show you're listening
|
| 55 |
+
- Share appropriate details about yourself/your work
|
| 56 |
+
- Handle awkward moments gracefully
|
| 57 |
+
|
| 58 |
+
### Supportive Language Learning:
|
| 59 |
+
- If users make small errors, naturally model correct language without stopping the flow
|
| 60 |
+
- Focus on communication over perfection
|
| 61 |
+
- Encourage them by showing interest in what they're saying
|
| 62 |
+
- Make them feel comfortable making mistakes
|
| 63 |
+
|
| 64 |
+
## Natural Handoff Triggers:
|
| 65 |
+
- **User speaks non-English** (immediate handoff)
|
| 66 |
+
- User seems genuinely lost or confused multiple times
|
| 67 |
+
- User explicitly asks for language help
|
| 68 |
+
- Communication completely breaks down
|
| 69 |
+
- User appears frustrated with language barriers
|
| 70 |
+
|
| 71 |
+
## Conversation Flow:
|
| 72 |
+
- Start conversations naturally for the situation
|
| 73 |
+
- Let conversations develop organically
|
| 74 |
+
- Don't force vocabulary usage - let it emerge naturally
|
| 75 |
+
- End conversations naturally when appropriate
|
| 76 |
+
|
| 77 |
+
Remember:
|
| 78 |
+
- You're not a teacher in roleplay mode - you're a real person doing your job who happens to be patient with English learners. Be genuine, warm, and human!
|
| 79 |
+
- Not respond too long or too short. But also can adapt to the user's communication style and needs.
|
| 80 |
+
"""
|
| 81 |
+
|
| 82 |
+
guiding_prompt = """# Role: Guiding Agent - Supportive Language Helper & Language Router
|
| 83 |
+
|
| 84 |
+
You are a patient, supportive language guide who helps users when they struggle with English communication. You are also responsible for handling users who speak non-English languages.
|
| 85 |
+
|
| 86 |
+
## Current Scenario Context:
|
| 87 |
+
{scenario_title}: {scenario_description}
|
| 88 |
+
Key vocabulary for this scenario: {key_vocabulary}
|
| 89 |
+
|
| 90 |
+
## Your Mission:
|
| 91 |
+
- Handle users who speak non-English languages and guide them to English
|
| 92 |
+
- Help users who are struggling with English communication
|
| 93 |
+
- Use simple, clear language and break things down step by step
|
| 94 |
+
- Provide examples and choices to make communication easier
|
| 95 |
+
- Build confidence and encourage attempts
|
| 96 |
+
- Prepare users to return to roleplay when they're ready
|
| 97 |
+
|
| 98 |
+
## Language Routing Protocol:
|
| 99 |
+
|
| 100 |
+
### When User Speaks Non-English Languages:
|
| 101 |
+
**Step 1: Polite Asking**
|
| 102 |
+
- Ask users about their current English level in their own language. If they are weak in English, encourage them and start teaching them.
|
| 103 |
+
|
| 104 |
+
**Step 2: Teaching**
|
| 105 |
+
- If users do not know English, use their own language to teach English, and if they know basic English, use English
|
| 106 |
+
- Start with very basic English
|
| 107 |
+
|
| 108 |
+
**Step 3: Begin English Teaching**
|
| 109 |
+
1. Ask them what they want to learn about related to the current topic. Give them some related suggestions to get feedback.
|
| 110 |
+
2. Teach them the related knowledge they need in the scope of learning English related to the topic, so that they have prior knowledge to practice Role-play
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
## Building from Zero:
|
| 115 |
+
1. **Basic greetings**: "Hello", "Hi", "Good morning"
|
| 116 |
+
2. **Essential phrases**: "Please", "Thank you", "Excuse me"
|
| 117 |
+
3. **Scenario basics**: Start with 2-3 key words for the situation
|
| 118 |
+
4. **Simple sentences**: "I want..." "I would like..." "Can I have..."
|
| 119 |
+
|
| 120 |
+
## Guiding Principles:
|
| 121 |
+
|
| 122 |
+
### Use Simple Language:
|
| 123 |
+
- Short, clear sentences
|
| 124 |
+
- Basic vocabulary (avoid complex words)
|
| 125 |
+
- One concept at a time
|
| 126 |
+
- Lots of examples and choices
|
| 127 |
+
|
| 128 |
+
### Supportive Approach:
|
| 129 |
+
- Encourage every attempt: "Good try!"
|
| 130 |
+
- Be patient with mistakes
|
| 131 |
+
- Focus on communication, not perfection
|
| 132 |
+
- Celebrate small victories
|
| 133 |
+
- **Extra patience for non-native speakers**: "Don't worry, English is difficult. You're doing great!"
|
| 134 |
+
|
| 135 |
+
### Step-by-Step Help:
|
| 136 |
+
- Break complex requests into smaller parts
|
| 137 |
+
- Give specific examples they can use
|
| 138 |
+
- Offer multiple choice options
|
| 139 |
+
- Model the language first
|
| 140 |
+
- **For beginners**: Start with single words, then phrases, then sentences
|
| 141 |
+
|
| 142 |
+
### Scenario-Specific Guidance:
|
| 143 |
+
- Teach key vocabulary for the current scenario
|
| 144 |
+
- Explain common phrases used in this situation
|
| 145 |
+
- Practice basic interactions before complex ones
|
| 146 |
+
- Connect learning to the roleplay context
|
| 147 |
+
|
| 148 |
+
## Teaching Techniques:
|
| 149 |
+
|
| 150 |
+
### For Absolute Beginners:
|
| 151 |
+
|
| 152 |
+
### Vocabulary Building:
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
### Phrase Practice:
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
### Choice-Based Learning:
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
### Error Correction:
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
## Building Confidence:
|
| 165 |
+
- "You're doing great! English is difficult, but you're learning fast."
|
| 166 |
+
- "Don't worry about mistakes. That's how we learn!"
|
| 167 |
+
- "Your English is getting better with each try."
|
| 168 |
+
- **For multilingual learners**: "Speaking multiple languages is amazing! English will be easier with practice."
|
| 169 |
+
|
| 170 |
+
## Transition Back to Roleplay:
|
| 171 |
+
- "Great! You're ready to try the real conversation now."
|
| 172 |
+
- "Perfect! Let's go back to the restaurant and practice with the waiter."
|
| 173 |
+
- "You know the words now. Let's use them in a real situation!"
|
| 174 |
+
|
| 175 |
+
## Signs to Return to Roleplay:
|
| 176 |
+
- User gives confident, complete responses IN ENGLISH
|
| 177 |
+
- User uses vocabulary correctly in context
|
| 178 |
+
- User asks to try the roleplay again
|
| 179 |
+
- User shows improved communication flow
|
| 180 |
+
- User can form basic sentences (5+ words) comfortably IN ENGLISH
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
Remember:
|
| 184 |
+
- Your job is to make English feel easier and help users gain confidence to communicate naturally in English! Always redirect non-English speakers to English practice.
|
| 185 |
+
- Be flexible in using the user's language or English based on their confidence to enhance user experience.
|
| 186 |
+
- Not respond too long or complexly to avoid overwhelming the user. Because the goal is to build their confidence and skills gradually.
|
| 187 |
+
"""
|
src/agents/role_play/scenarios.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
SCENARIOS = [
|
| 2 |
+
{
|
| 3 |
+
"id": "student_visa_interview",
|
| 4 |
+
"scenario_title": "Student Visa Interview",
|
| 5 |
+
"scenario_description": "Learn about the challenges and benefits of starting a small business, then share what kind of business you would start. You are a student applying for a student visa. I am the visa interviewer.",
|
| 6 |
+
"scenario_context": "A formal visa interview office at an embassy or consulate",
|
| 7 |
+
"your_role": "student",
|
| 8 |
+
"key_vocabulary": [
|
| 9 |
+
"pursue higher education",
|
| 10 |
+
"broaden my horizons",
|
| 11 |
+
"international exposure",
|
| 12 |
+
"cultural diversity",
|
| 13 |
+
"academic excellence",
|
| 14 |
+
"globally recognized degree",
|
| 15 |
+
"cutting-edge facilities",
|
| 16 |
+
"research opportunities",
|
| 17 |
+
"tuition fees",
|
| 18 |
+
"financial support",
|
| 19 |
+
"scholarship",
|
| 20 |
+
"sponsorship letter",
|
| 21 |
+
"post-graduation plans",
|
| 22 |
+
],
|
| 23 |
+
"topics_covered": [
|
| 24 |
+
"Study Plans",
|
| 25 |
+
"University Choice",
|
| 26 |
+
"Academic Capability",
|
| 27 |
+
"Financial Status",
|
| 28 |
+
"Post-Graduation Plans",
|
| 29 |
+
],
|
| 30 |
+
"follow_up_questions": {
|
| 31 |
+
"Study Plans": [
|
| 32 |
+
"Why did you decide to pursue higher education abroad instead of in your home country?",
|
| 33 |
+
"How will studying overseas help you broaden your horizons?",
|
| 34 |
+
"What challenges do you expect to face in a foreign academic environment?",
|
| 35 |
+
"How long is your course, and what is your study schedule like?",
|
| 36 |
+
"Have you researched the teaching methods used in your chosen program?",
|
| 37 |
+
],
|
| 38 |
+
"University Choice": [
|
| 39 |
+
"Why did you choose this university over others?",
|
| 40 |
+
"How do you think the academic excellence of this institution will benefit you?",
|
| 41 |
+
"Have you looked into the research opportunities your university offers?",
|
| 42 |
+
"How will the cultural diversity on campus influence your experience?",
|
| 43 |
+
"What do you know about the city where your university is located?",
|
| 44 |
+
],
|
| 45 |
+
"Academic Capability": [
|
| 46 |
+
"How does your academic background prepare you for this course?",
|
| 47 |
+
"Can you give an example of a project or subject you excelled at in the past?",
|
| 48 |
+
"How will you make use of the cutting-edge facilities provided by the university?",
|
| 49 |
+
"How confident are you in adapting to a different academic system?",
|
| 50 |
+
"What skills do you think will help you succeed in your studies abroad?",
|
| 51 |
+
],
|
| 52 |
+
"Financial Status": [
|
| 53 |
+
"How will you fund your tuition fees and living expenses?",
|
| 54 |
+
"Can you provide details about your financial support from family?",
|
| 55 |
+
"Do you have a scholarship or proof of funds?",
|
| 56 |
+
"How have you prepared financially for unexpected costs?",
|
| 57 |
+
"Can you show me your bank statement and sponsorship letter?",
|
| 58 |
+
],
|
| 59 |
+
"Post-Graduation Plans": [
|
| 60 |
+
"What will you do after you complete your degree?",
|
| 61 |
+
"How will your globally recognized degree help you in your career?",
|
| 62 |
+
"Do you plan to work overseas or return to your home country?",
|
| 63 |
+
"How will you apply the knowledge acquired during your studies?",
|
| 64 |
+
"What is your long-term goal after graduation?",
|
| 65 |
+
],
|
| 66 |
+
},
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"id": "ordering_at_restaurant",
|
| 70 |
+
"scenario_title": "Ordering At A Restaurant",
|
| 71 |
+
"scenario_description": "Practice ordering food, asking about the menu, and talking to a waiter. You are a customer at a restaurant. I am the waiter/waitress.",
|
| 72 |
+
"scenario_context": "A busy restaurant with various seating options and a diverse menu",
|
| 73 |
+
"your_role": "customer",
|
| 74 |
+
"key_vocabulary": [
|
| 75 |
+
"table for two, please",
|
| 76 |
+
"do you have a reservation?",
|
| 77 |
+
"non-smoking section",
|
| 78 |
+
"window seat",
|
| 79 |
+
"outdoor seating",
|
| 80 |
+
"could we have the bill, please?",
|
| 81 |
+
"do you take credit cards?",
|
| 82 |
+
"signature dish",
|
| 83 |
+
"dietary restrictions",
|
| 84 |
+
"sauce served separately",
|
| 85 |
+
"steak cooked",
|
| 86 |
+
"pair with a drink",
|
| 87 |
+
"vegetarian options",
|
| 88 |
+
"receipt",
|
| 89 |
+
"cash or card",
|
| 90 |
+
],
|
| 91 |
+
"topics_covered": [
|
| 92 |
+
"Getting a Table",
|
| 93 |
+
"Asking About the Menu",
|
| 94 |
+
"Making a Food Order",
|
| 95 |
+
"Special Requests or Allergies",
|
| 96 |
+
"Paying the Bill",
|
| 97 |
+
],
|
| 98 |
+
"follow_up_questions": {
|
| 99 |
+
"Getting a Table": [
|
| 100 |
+
"Would you like to sit inside or outside?",
|
| 101 |
+
"How many people will be joining you today?",
|
| 102 |
+
"Do you have a reservation under your name?",
|
| 103 |
+
],
|
| 104 |
+
"Asking About the Menu": [
|
| 105 |
+
"Are you looking for something light or filling?",
|
| 106 |
+
"Would you like to try our signature dish?",
|
| 107 |
+
"Do you prefer meat, seafood, or vegetarian options?",
|
| 108 |
+
],
|
| 109 |
+
"Making a Food Order": [
|
| 110 |
+
"Would you like any sides with that?",
|
| 111 |
+
"How would you like your steak cooked?",
|
| 112 |
+
"Would you like to pair it with a drink?",
|
| 113 |
+
],
|
| 114 |
+
"Special Requests or Allergies": [
|
| 115 |
+
"Do you have any dietary restrictions?",
|
| 116 |
+
"Should we avoid using certain ingredients?",
|
| 117 |
+
"Would you like the sauce served separately?",
|
| 118 |
+
],
|
| 119 |
+
"Paying the Bill": [
|
| 120 |
+
"Would you like to pay together or separately?",
|
| 121 |
+
"Would you like the receipt?",
|
| 122 |
+
"Are you paying by cash or card?",
|
| 123 |
+
],
|
| 124 |
+
},
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"id": "going_shopping",
|
| 128 |
+
"scenario_title": "Going Shopping",
|
| 129 |
+
"scenario_description": "Practice asking about prices, sizes, and items while shopping. You are a customer looking for items in a store. I am the shop assistant.",
|
| 130 |
+
"scenario_context": "A retail store with various departments and products",
|
| 131 |
+
"your_role": "customer",
|
| 132 |
+
"key_vocabulary": [
|
| 133 |
+
"excuse me, could you help me?",
|
| 134 |
+
"I'm looking for...",
|
| 135 |
+
"do you have this in stock?",
|
| 136 |
+
"could you show me where it is?",
|
| 137 |
+
"what size do you usually wear?",
|
| 138 |
+
"would you like to try it on?",
|
| 139 |
+
"does it fit comfortably?",
|
| 140 |
+
"specific price range",
|
| 141 |
+
"casual or formal",
|
| 142 |
+
"specific brand",
|
| 143 |
+
"different size",
|
| 144 |
+
"paying by cash or card",
|
| 145 |
+
"would you like a bag?",
|
| 146 |
+
"exchange it for another item",
|
| 147 |
+
"other options",
|
| 148 |
+
],
|
| 149 |
+
"topics_covered": [
|
| 150 |
+
"Asking for Help",
|
| 151 |
+
"Describing What You're Looking For",
|
| 152 |
+
"Asking About Price or Size",
|
| 153 |
+
"Trying or Testing Products",
|
| 154 |
+
"Making the Purchase or Returning",
|
| 155 |
+
],
|
| 156 |
+
"follow_up_questions": {
|
| 157 |
+
"Asking for Help": [
|
| 158 |
+
"How can I assist you today?",
|
| 159 |
+
"Are you looking for anything in particular?",
|
| 160 |
+
"Do you need help finding your size?",
|
| 161 |
+
],
|
| 162 |
+
"Describing What You're Looking For": [
|
| 163 |
+
"What color or style are you interested in?",
|
| 164 |
+
"Do you want something casual or formal?",
|
| 165 |
+
"Is there a specific brand you prefer?",
|
| 166 |
+
],
|
| 167 |
+
"Asking About Price or Size": [
|
| 168 |
+
"Are you looking for something in a specific price range?",
|
| 169 |
+
"What size do you usually wear?",
|
| 170 |
+
"Would you like to see other options in your size?",
|
| 171 |
+
],
|
| 172 |
+
"Trying or Testing Products": [
|
| 173 |
+
"Would you like to try it on?",
|
| 174 |
+
"Does it fit comfortably?",
|
| 175 |
+
"Do you need a different size?",
|
| 176 |
+
],
|
| 177 |
+
"Making the Purchase or Returning": [
|
| 178 |
+
"Will you be paying by cash or card?",
|
| 179 |
+
"Would you like a bag for that?",
|
| 180 |
+
"Would you like to exchange it for another item?",
|
| 181 |
+
],
|
| 182 |
+
},
|
| 183 |
+
},
|
| 184 |
+
]
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def get_scenarios():
|
| 188 |
+
return SCENARIOS
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def get_scenario_by_id(scenario_id: str):
|
| 192 |
+
for scenario in SCENARIOS:
|
| 193 |
+
if scenario["id"] == scenario_id:
|
| 194 |
+
return scenario
|
| 195 |
+
return None
|
src/agents/role_play/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/tools/__pycache__/crawl.cpython-311.pyc
ADDED
|
Binary file (1.34 kB). View file
|
|
|
src/agents/tools/crawl.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
| 2 |
+
# SPDX-License-Identifier: MIT
|
| 3 |
+
|
| 4 |
+
from typing import Annotated
|
| 5 |
+
|
| 6 |
+
from langchain_core.tools import tool
|
| 7 |
+
|
| 8 |
+
from src.config.crawler.crawler import Crawler
|
| 9 |
+
from loguru import logger
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@tool
|
| 13 |
+
def crawl_tool(
|
| 14 |
+
url: Annotated[str, "The url to crawl."],
|
| 15 |
+
) -> str:
|
| 16 |
+
"""Use this to crawl a url and get a readable content in markdown format."""
|
| 17 |
+
try:
|
| 18 |
+
crawler = Crawler()
|
| 19 |
+
article = crawler.crawl(url)
|
| 20 |
+
return {"url": url, "crawled_content": article.to_markdown()[:1000]}
|
| 21 |
+
except BaseException as e:
|
| 22 |
+
error_msg = f"Failed to crawl. Error: {repr(e)}"
|
| 23 |
+
logger.error(error_msg)
|
| 24 |
+
return error_msg
|
src/apis/.DS_Store
ADDED
|
Binary file (8.2 kB). View file
|
|
|
src/apis/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (166 Bytes). View file
|
|
|
src/apis/__pycache__/create_app.cpython-311.pyc
ADDED
|
Binary file (1.12 kB). View file
|
|
|
src/apis/config/__pycache__/firebase_config.cpython-311.pyc
ADDED
|
Binary file (1.79 kB). View file
|
|
|
src/apis/create_app.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
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():
|
| 12 |
+
app = FastAPI(docs_url="/", title="API")
|
| 13 |
+
|
| 14 |
+
app.add_middleware(
|
| 15 |
+
CORSMiddleware,
|
| 16 |
+
allow_origins=["*"],
|
| 17 |
+
allow_credentials=True,
|
| 18 |
+
allow_methods=["*"],
|
| 19 |
+
allow_headers=["*"],
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
return app
|
src/apis/interfaces/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
src/apis/interfaces/__pycache__/api_interface.cpython-311.pyc
ADDED
|
Binary file (7.32 kB). View file
|
|
|
src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc
ADDED
|
Binary file (1.74 kB). View file
|
|
|
src/apis/interfaces/api_interface.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import Optional
|
| 3 |
+
from src.apis.models.BaseModel import BaseDocument
|
| 4 |
+
from typing import List, Union
|
| 5 |
+
|
src/apis/interfaces/auth_interface.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
|
src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc
ADDED
|
Binary file (2.2 kB). View file
|
|
|
src/apis/middlewares/auth_middleware.py
ADDED
|
File without changes
|
src/apis/models/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
src/apis/models/BaseModel.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import Optional
|
| 3 |
+
from datetime import datetime
|
| 4 |
+
from src.utils.logger import get_date_time
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class BaseDocument(BaseModel):
|
| 8 |
+
created_at: Optional[datetime] = Field(
|
| 9 |
+
default_factory=lambda: get_date_time().replace(tzinfo=None)
|
| 10 |
+
)
|
| 11 |
+
updated_at: Optional[datetime] = Field(
|
| 12 |
+
default_factory=lambda: get_date_time().replace(tzinfo=None)
|
| 13 |
+
)
|
| 14 |
+
expire_at: Optional[datetime] = None
|
| 15 |
+
|
| 16 |
+
class Config:
|
| 17 |
+
arbitrary_types_allowed = True
|
src/apis/models/__pycache__/BaseModel.cpython-311.pyc
ADDED
|
Binary file (1.64 kB). View file
|
|
|
src/apis/models/__pycache__/destination_models.cpython-311.pyc
ADDED
|
Binary file (2.12 kB). View file
|
|
|
src/apis/models/__pycache__/hotel_models.cpython-311.pyc
ADDED
|
Binary file (2.14 kB). View file
|
|
|
src/apis/models/__pycache__/post_models.cpython-311.pyc
ADDED
|
Binary file (2.73 kB). View file
|
|
|
src/apis/models/__pycache__/schedule_models.cpython-311.pyc
ADDED
|
Binary file (1.8 kB). View file
|
|
|
src/apis/models/__pycache__/user_models.cpython-311.pyc
ADDED
|
Binary file (2.41 kB). View file
|
|
|
src/apis/models/user_models.py
ADDED
|
File without changes
|
src/apis/providers/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
src/apis/providers/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (271 Bytes). View file
|
|
|
src/apis/providers/__pycache__/firebase_provider.cpython-311.pyc
ADDED
|
Binary file (4.75 kB). View file
|
|
|