ABAO77 commited on
Commit
4909ef6
·
1 Parent(s): a4cb278

remove conversation management

Browse files
src/apis/routes/chat_route.py CHANGED
@@ -1,8 +1,6 @@
1
  from fastapi import (
2
  APIRouter,
3
  status,
4
- Depends,
5
- BackgroundTasks,
6
  HTTPException,
7
  File,
8
  UploadFile,
@@ -12,12 +10,9 @@ from fastapi.responses import JSONResponse
12
  from src.utils.logger import logger
13
  from src.agents.role_play.flow import role_play_agent
14
  from pydantic import BaseModel, Field
15
- from typing import List, Dict, Any, Optional
16
- from src.agents.role_play.scenarios import get_scenarios, get_scenario_by_id
17
  import json
18
- import os
19
- import uuid
20
- from datetime import datetime
21
  import base64
22
 
23
  router = APIRouter(prefix="/ai", tags=["AI"])
@@ -31,91 +26,6 @@ class RoleplayRequest(BaseModel):
31
  scenario: Dict[str, Any] = Field(..., description="The scenario for the roleplay")
32
 
33
 
34
- class SessionRequest(BaseModel):
35
- session_id: str = Field(..., description="Session ID to perform operations on")
36
-
37
-
38
- class CreateSessionRequest(BaseModel):
39
- name: str = Field(..., description="Name for the new session")
40
-
41
-
42
- class UpdateSessionRequest(BaseModel):
43
- session_id: str = Field(..., description="Session ID to update")
44
- name: str = Field(..., description="New name for the session")
45
-
46
-
47
- # Session management helper functions
48
- SESSIONS_FILE = "sessions.json"
49
-
50
-
51
- def load_sessions() -> List[Dict[str, Any]]:
52
- """Load sessions from JSON file"""
53
- try:
54
- if os.path.exists(SESSIONS_FILE):
55
- with open(SESSIONS_FILE, "r", encoding="utf-8") as f:
56
- return json.load(f)
57
- return []
58
- except Exception as e:
59
- logger.error(f"Error loading sessions: {str(e)}")
60
- return []
61
-
62
-
63
- def save_sessions(sessions: List[Dict[str, Any]]):
64
- """Save sessions to JSON file"""
65
- try:
66
- with open(SESSIONS_FILE, "w", encoding="utf-8") as f:
67
- json.dump(sessions, f, ensure_ascii=False, indent=2, default=str)
68
- except Exception as e:
69
- logger.error(f"Error saving sessions: {str(e)}")
70
-
71
-
72
- def create_session(name: str) -> Dict[str, Any]:
73
- """Create a new session"""
74
- session_id = str(uuid.uuid4())
75
- session = {
76
- "id": session_id,
77
- "name": name,
78
- "created_at": datetime.now().isoformat(),
79
- "last_message": None,
80
- "message_count": 0,
81
- }
82
-
83
- sessions = load_sessions()
84
- sessions.append(session)
85
- save_sessions(sessions)
86
-
87
- return session
88
-
89
-
90
- def get_session_by_id(session_id: str) -> Optional[Dict[str, Any]]:
91
- """Get session by ID"""
92
- sessions = load_sessions()
93
- return next((s for s in sessions if s["id"] == session_id), None)
94
-
95
-
96
- def update_session_last_message(session_id: str, message: str):
97
- """Update session's last message"""
98
- sessions = load_sessions()
99
- for session in sessions:
100
- if session["id"] == session_id:
101
- session["last_message"] = message
102
- session["message_count"] = session.get("message_count", 0) + 1
103
- break
104
- save_sessions(sessions)
105
-
106
-
107
- def delete_session_by_id(session_id: str) -> bool:
108
- """Delete session by ID"""
109
- sessions = load_sessions()
110
- original_count = len(sessions)
111
- sessions = [s for s in sessions if s["id"] != session_id]
112
-
113
- if len(sessions) < original_count:
114
- save_sessions(sessions)
115
- return True
116
- return False
117
-
118
-
119
  @router.get("/scenarios", status_code=status.HTTP_200_OK)
120
  async def list_scenarios():
121
  """Get all available scenarios"""
@@ -134,7 +44,7 @@ async def roleplay(
134
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
135
  ):
136
  """Send a message (text or audio) to the roleplay agent"""
137
-
138
  # Validate that at least one input is provided
139
  if not text_message and not audio_file:
140
  raise HTTPException(
@@ -211,8 +121,6 @@ async def roleplay(
211
  },
212
  {"configurable": {"thread_id": session_id}},
213
  )
214
- last_message = text_message if text_message else "[Audio message]"
215
- update_session_last_message(session_id, last_message)
216
 
217
  # Extract AI response content
218
  ai_response = response["messages"][-1].content
@@ -223,160 +131,3 @@ async def roleplay(
223
  except Exception as e:
224
  logger.error(f"Error in roleplay: {str(e)}")
225
  raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
226
-
227
-
228
- @router.post("/get-messages", status_code=status.HTTP_200_OK)
229
- async def get_messages(request: SessionRequest):
230
- """Get all messages from a conversation session"""
231
- try:
232
-
233
- # Create agent instance
234
- agent = role_play_agent()
235
-
236
- # Get current state
237
- current_state = agent.get_state(
238
- {"configurable": {"thread_id": request.session_id}}
239
- )
240
-
241
- if not current_state or not current_state.values:
242
- return JSONResponse(
243
- content={
244
- "session_id": request.session_id,
245
- "messages": [],
246
- "total_messages": 0,
247
- }
248
- )
249
-
250
- # Extract messages from state
251
- messages = []
252
- if "messages" in current_state.values:
253
- raw_messages = current_state.values["messages"]
254
-
255
- for msg in raw_messages:
256
- # Convert message object to dict format
257
- if hasattr(msg, "content") and hasattr(msg, "type"):
258
- messages.append(
259
- {
260
- "role": getattr(msg, "type", "unknown"),
261
- "content": getattr(msg, "content", ""),
262
- "timestamp": getattr(msg, "timestamp", None),
263
- }
264
- )
265
- elif hasattr(msg, "content"):
266
- # Handle different message formats
267
- role = (
268
- "human"
269
- if hasattr(msg, "__class__")
270
- and "Human" in msg.__class__.__name__
271
- else "ai"
272
- )
273
- messages.append(
274
- {
275
- "role": role,
276
- "content": msg.content,
277
- "timestamp": getattr(msg, "timestamp", None),
278
- }
279
- )
280
- else:
281
- # Fallback for unexpected message format
282
- messages.append(
283
- {"role": "unknown", "content": str(msg), "timestamp": None}
284
- )
285
-
286
- return JSONResponse(
287
- content={
288
- "session_id": request.session_id,
289
- "messages": messages,
290
- "total_messages": len(messages),
291
- }
292
- )
293
-
294
- except Exception as e:
295
- logger.error(
296
- f"Error getting messages for session {request.session_id}: {str(e)}"
297
- )
298
- raise HTTPException(status_code=500, detail=f"Failed to get messages: {str(e)}")
299
-
300
-
301
- @router.get("/sessions", status_code=status.HTTP_200_OK)
302
- async def get_sessions():
303
- """Get all sessions"""
304
- try:
305
- sessions = load_sessions()
306
- return JSONResponse(content={"sessions": sessions})
307
- except Exception as e:
308
- logger.error(f"Error getting sessions: {str(e)}")
309
- raise HTTPException(status_code=500, detail=f"Failed to get sessions: {str(e)}")
310
-
311
-
312
- @router.post("/sessions", status_code=status.HTTP_201_CREATED)
313
- async def create_new_session(request: CreateSessionRequest):
314
- """Create a new session"""
315
- try:
316
- session = create_session(request.name)
317
- return JSONResponse(content={"session": session})
318
- except Exception as e:
319
- logger.error(f"Error creating session: {str(e)}")
320
- raise HTTPException(
321
- status_code=500, detail=f"Failed to create session: {str(e)}"
322
- )
323
-
324
-
325
- @router.get("/sessions/{session_id}", status_code=status.HTTP_200_OK)
326
- async def get_session(session_id: str):
327
- """Get a specific session by ID"""
328
- try:
329
- session = get_session_by_id(session_id)
330
- if not session:
331
- raise HTTPException(status_code=404, detail="Session not found")
332
- return JSONResponse(content={"session": session})
333
- except HTTPException:
334
- raise
335
- except Exception as e:
336
- logger.error(f"Error getting session {session_id}: {str(e)}")
337
- raise HTTPException(status_code=500, detail=f"Failed to get session: {str(e)}")
338
-
339
-
340
- @router.put("/sessions/{session_id}", status_code=status.HTTP_200_OK)
341
- async def update_session(session_id: str, request: UpdateSessionRequest):
342
- """Update a session"""
343
- try:
344
- sessions = load_sessions()
345
- session_found = False
346
-
347
- for session in sessions:
348
- if session["id"] == session_id:
349
- session["name"] = request.name
350
- session_found = True
351
- break
352
-
353
- if not session_found:
354
- raise HTTPException(status_code=404, detail="Session not found")
355
-
356
- save_sessions(sessions)
357
- updated_session = get_session_by_id(session_id)
358
- return JSONResponse(content={"session": updated_session})
359
- except HTTPException:
360
- raise
361
- except Exception as e:
362
- logger.error(f"Error updating session {session_id}: {str(e)}")
363
- raise HTTPException(
364
- status_code=500, detail=f"Failed to update session: {str(e)}"
365
- )
366
-
367
-
368
- @router.delete("/sessions/{session_id}", status_code=status.HTTP_200_OK)
369
- async def delete_session(session_id: str):
370
- """Delete a session"""
371
- try:
372
- success = delete_session_by_id(session_id)
373
- if not success:
374
- raise HTTPException(status_code=404, detail="Session not found")
375
- return JSONResponse(content={"message": "Session deleted successfully"})
376
- except HTTPException:
377
- raise
378
- except Exception as e:
379
- logger.error(f"Error deleting session {session_id}: {str(e)}")
380
- raise HTTPException(
381
- status_code=500, detail=f"Failed to delete session: {str(e)}"
382
- )
 
1
  from fastapi import (
2
  APIRouter,
3
  status,
 
 
4
  HTTPException,
5
  File,
6
  UploadFile,
 
10
  from src.utils.logger import logger
11
  from src.agents.role_play.flow import role_play_agent
12
  from pydantic import BaseModel, Field
13
+ from typing import Dict, Any, Optional
14
+ from src.agents.role_play.scenarios import get_scenarios
15
  import json
 
 
 
16
  import base64
17
 
18
  router = APIRouter(prefix="/ai", tags=["AI"])
 
26
  scenario: Dict[str, Any] = Field(..., description="The scenario for the roleplay")
27
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  @router.get("/scenarios", status_code=status.HTTP_200_OK)
30
  async def list_scenarios():
31
  """Get all available scenarios"""
 
44
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
45
  ):
46
  """Send a message (text or audio) to the roleplay agent"""
47
+ logger.info(f"Received roleplay request: {session_id}")
48
  # Validate that at least one input is provided
49
  if not text_message and not audio_file:
50
  raise HTTPException(
 
121
  },
122
  {"configurable": {"thread_id": session_id}},
123
  )
 
 
124
 
125
  # Extract AI response content
126
  ai_response = response["messages"][-1].content
 
131
  except Exception as e:
132
  logger.error(f"Error in roleplay: {str(e)}")
133
  raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/apis/routes/lesson_route.py CHANGED
@@ -39,15 +39,17 @@ class LessonPracticeRequest(BaseModel):
39
  def load_lessons_from_file() -> List[Lesson]:
40
  """Load lessons from the JSON file"""
41
  try:
42
- lessons_file_path = os.path.join(os.path.dirname(__file__), "..", "..", "data", "lessons.json")
43
-
 
 
44
  if not os.path.exists(lessons_file_path):
45
  logger.warning(f"Lessons file not found at {lessons_file_path}")
46
  return []
47
-
48
- with open(lessons_file_path, 'r', encoding='utf-8') as file:
49
  lessons_data = json.load(file)
50
-
51
  # Convert to Lesson objects
52
  lessons = []
53
  for lesson_data in lessons_data:
@@ -55,9 +57,11 @@ def load_lessons_from_file() -> List[Lesson]:
55
  lesson = Lesson(**lesson_data)
56
  lessons.append(lesson)
57
  except Exception as e:
58
- logger.error(f"Error parsing lesson {lesson_data.get('id', 'unknown')}: {str(e)}")
 
 
59
  continue
60
-
61
  return lessons
62
  except Exception as e:
63
  logger.error(f"Error loading lessons: {str(e)}")
@@ -68,22 +72,19 @@ def load_lessons_from_file() -> List[Lesson]:
68
  async def get_all_lessons():
69
  """
70
  Get all available lessons
71
-
72
  Returns:
73
  LessonResponse: Contains list of all lessons and total count
74
  """
75
  try:
76
  lessons = load_lessons_from_file()
77
-
78
- return LessonResponse(
79
- lessons=lessons,
80
- total=len(lessons)
81
- )
82
  except Exception as e:
83
  logger.error(f"Error retrieving lessons: {str(e)}")
84
  raise HTTPException(
85
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
86
- detail="Failed to retrieve lessons"
87
  )
88
 
89
 
@@ -91,25 +92,25 @@ async def get_all_lessons():
91
  async def get_lesson_by_id(lesson_id: str):
92
  """
93
  Get a specific lesson by ID
94
-
95
  Args:
96
  lesson_id (str): The unique identifier of the lesson
97
-
98
  Returns:
99
  LessonDetailResponse: Contains the lesson details
100
  """
101
  try:
102
  lessons = load_lessons_from_file()
103
-
104
  # Find the lesson with the specified ID
105
  lesson = next((l for l in lessons if l.id == lesson_id), None)
106
-
107
  if not lesson:
108
  raise HTTPException(
109
  status_code=status.HTTP_404_NOT_FOUND,
110
- detail=f"Lesson with ID '{lesson_id}' not found"
111
  )
112
-
113
  return LessonDetailResponse(lesson=lesson)
114
  except HTTPException:
115
  raise
@@ -117,7 +118,7 @@ async def get_lesson_by_id(lesson_id: str):
117
  logger.error(f"Error retrieving lesson {lesson_id}: {str(e)}")
118
  raise HTTPException(
119
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
120
- detail="Failed to retrieve lesson"
121
  )
122
 
123
 
@@ -125,31 +126,27 @@ async def get_lesson_by_id(lesson_id: str):
125
  async def search_lessons_by_unit(unit_name: str):
126
  """
127
  Search lessons by unit name (case-insensitive partial match)
128
-
129
  Args:
130
  unit_name (str): Part of the unit name to search for
131
-
132
  Returns:
133
  LessonResponse: Contains list of matching lessons
134
  """
135
  try:
136
  lessons = load_lessons_from_file()
137
-
138
  # Filter lessons by unit name (case-insensitive partial match)
139
  matching_lessons = [
140
- lesson for lesson in lessons
141
- if unit_name.lower() in lesson.unit.lower()
142
  ]
143
-
144
- return LessonResponse(
145
- lessons=matching_lessons,
146
- total=len(matching_lessons)
147
- )
148
  except Exception as e:
149
  logger.error(f"Error searching lessons by unit '{unit_name}': {str(e)}")
150
  raise HTTPException(
151
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
152
- detail="Failed to search lessons"
153
  )
154
 
155
 
@@ -158,9 +155,7 @@ async def chat(
158
  session_id: str = Form(
159
  ..., description="Session ID for tracking user interactions"
160
  ),
161
- lesson_data: str = Form(
162
- ..., description="The lesson data as JSON string"
163
- ),
164
  text_message: Optional[str] = Form(None, description="Text message from user"),
165
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
166
  ):
@@ -242,7 +237,7 @@ async def chat(
242
  },
243
  {"configurable": {"thread_id": session_id}},
244
  )
245
-
246
  # Extract AI response content
247
  ai_response = response["messages"][-1].content
248
  logger.info(f"AI response: {ai_response}")
 
39
  def load_lessons_from_file() -> List[Lesson]:
40
  """Load lessons from the JSON file"""
41
  try:
42
+ lessons_file_path = os.path.join(
43
+ os.path.dirname(__file__), "..", "..", "data", "lessons.json"
44
+ )
45
+
46
  if not os.path.exists(lessons_file_path):
47
  logger.warning(f"Lessons file not found at {lessons_file_path}")
48
  return []
49
+
50
+ with open(lessons_file_path, "r", encoding="utf-8") as file:
51
  lessons_data = json.load(file)
52
+
53
  # Convert to Lesson objects
54
  lessons = []
55
  for lesson_data in lessons_data:
 
57
  lesson = Lesson(**lesson_data)
58
  lessons.append(lesson)
59
  except Exception as e:
60
+ logger.error(
61
+ f"Error parsing lesson {lesson_data.get('id', 'unknown')}: {str(e)}"
62
+ )
63
  continue
64
+
65
  return lessons
66
  except Exception as e:
67
  logger.error(f"Error loading lessons: {str(e)}")
 
72
  async def get_all_lessons():
73
  """
74
  Get all available lessons
75
+
76
  Returns:
77
  LessonResponse: Contains list of all lessons and total count
78
  """
79
  try:
80
  lessons = load_lessons_from_file()
81
+
82
+ return LessonResponse(lessons=lessons, total=len(lessons))
 
 
 
83
  except Exception as e:
84
  logger.error(f"Error retrieving lessons: {str(e)}")
85
  raise HTTPException(
86
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
87
+ detail="Failed to retrieve lessons",
88
  )
89
 
90
 
 
92
  async def get_lesson_by_id(lesson_id: str):
93
  """
94
  Get a specific lesson by ID
95
+
96
  Args:
97
  lesson_id (str): The unique identifier of the lesson
98
+
99
  Returns:
100
  LessonDetailResponse: Contains the lesson details
101
  """
102
  try:
103
  lessons = load_lessons_from_file()
104
+
105
  # Find the lesson with the specified ID
106
  lesson = next((l for l in lessons if l.id == lesson_id), None)
107
+
108
  if not lesson:
109
  raise HTTPException(
110
  status_code=status.HTTP_404_NOT_FOUND,
111
+ detail=f"Lesson with ID '{lesson_id}' not found",
112
  )
113
+
114
  return LessonDetailResponse(lesson=lesson)
115
  except HTTPException:
116
  raise
 
118
  logger.error(f"Error retrieving lesson {lesson_id}: {str(e)}")
119
  raise HTTPException(
120
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
121
+ detail="Failed to retrieve lesson",
122
  )
123
 
124
 
 
126
  async def search_lessons_by_unit(unit_name: str):
127
  """
128
  Search lessons by unit name (case-insensitive partial match)
129
+
130
  Args:
131
  unit_name (str): Part of the unit name to search for
132
+
133
  Returns:
134
  LessonResponse: Contains list of matching lessons
135
  """
136
  try:
137
  lessons = load_lessons_from_file()
138
+
139
  # Filter lessons by unit name (case-insensitive partial match)
140
  matching_lessons = [
141
+ lesson for lesson in lessons if unit_name.lower() in lesson.unit.lower()
 
142
  ]
143
+
144
+ return LessonResponse(lessons=matching_lessons, total=len(matching_lessons))
 
 
 
145
  except Exception as e:
146
  logger.error(f"Error searching lessons by unit '{unit_name}': {str(e)}")
147
  raise HTTPException(
148
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
149
+ detail="Failed to search lessons",
150
  )
151
 
152
 
 
155
  session_id: str = Form(
156
  ..., description="Session ID for tracking user interactions"
157
  ),
158
+ lesson_data: str = Form(..., description="The lesson data as JSON string"),
 
 
159
  text_message: Optional[str] = Form(None, description="Text message from user"),
160
  audio_file: Optional[UploadFile] = File(None, description="Audio file from user"),
161
  ):
 
237
  },
238
  {"configurable": {"thread_id": session_id}},
239
  )
240
+
241
  # Extract AI response content
242
  ai_response = response["messages"][-1].content
243
  logger.info(f"AI response: {ai_response}")
src/apis/routes/user_route.py CHANGED
@@ -1,7 +1,6 @@
1
  from fastapi import APIRouter, status, Depends, BackgroundTasks
2
  from fastapi.responses import JSONResponse
3
  from src.utils.logger import logger
4
- from src.utils.redis import set_key_redis, delete_key_redis
5
 
6
 
7
  router = APIRouter(prefix="/user", tags=["User"])
 
1
  from fastapi import APIRouter, status, Depends, BackgroundTasks
2
  from fastapi.responses import JSONResponse
3
  from src.utils.logger import logger
 
4
 
5
 
6
  router = APIRouter(prefix="/user", tags=["User"])
src/utils/redis.py DELETED
@@ -1,18 +0,0 @@
1
- import redis.asyncio as redis
2
-
3
- # redis_client = redis.from_url(
4
- # RedisCfg.REDIS_URL, encoding="utf-8", decode_responses=True
5
- # )
6
-
7
-
8
- async def set_key_redis(key, value, time=300):
9
- return None #redis_client.set(key, value, time)
10
-
11
-
12
- async def get_key_redis(key):
13
-
14
- return None #await redis_client.get(key)
15
-
16
-
17
- async def delete_key_redis(key):
18
- return None#redis_client.delete(key)