seawolf2357 commited on
Commit
1283bb7
·
verified ·
1 Parent(s): f98e6c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -40
app.py CHANGED
@@ -755,6 +755,13 @@ HTML_CONTENT = """<!DOCTYPE html>
755
  const message = textInput.value.trim();
756
  if (!message) return;
757
 
 
 
 
 
 
 
 
758
  // Add user message to chat
759
  addMessage('user', message);
760
  textInput.value = '';
@@ -1246,13 +1253,18 @@ class PersonalAssistantDB:
1246
  @staticmethod
1247
  async def save_message(session_id: str, role: str, content: str):
1248
  """Save a message to the database"""
 
 
 
 
 
1249
  # Detect language
1250
  detected_language = None
1251
  try:
1252
  if content and len(content) > 10:
1253
  detected_language = detect(content)
1254
- except LangDetectException:
1255
- pass
1256
 
1257
  async with aiosqlite.connect(DB_PATH) as db:
1258
  await db.execute(
@@ -1390,7 +1402,7 @@ class PersonalAssistantDB:
1390
  # Prepare conversation text for analysis
1391
  conversation_text = "\n".join([
1392
  f"{msg['role']}: {msg['content']}"
1393
- for msg in messages
1394
  ])
1395
 
1396
  # Use GPT to extract memories
@@ -1484,10 +1496,11 @@ def format_memories_for_prompt(memories: Dict[str, List[str]]) -> str:
1484
 
1485
  memory_text = "\n\n=== 기억된 정보 ===\n"
1486
  for category, items in memories.items():
1487
- if items:
1488
  memory_text += f"\n[{category}]\n"
1489
  for item in items:
1490
- memory_text += f"- {item}\n"
 
1491
 
1492
  return memory_text
1493
 
@@ -1496,6 +1509,10 @@ async def process_text_chat(message: str, web_search_enabled: bool, session_id:
1496
  user_name: str = "", memories: Dict = None) -> Dict[str, str]:
1497
  """Process text chat using GPT-4o-mini model"""
1498
  try:
 
 
 
 
1499
  # Check for stop words
1500
  stop_words = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"]
1501
  if any(word in message.lower() for word in stop_words):
@@ -1519,7 +1536,7 @@ IMPORTANT: Give only ONE response. Do not repeat or give multiple answers."""
1519
  messages = [{"role": "system", "content": base_prompt}]
1520
 
1521
  # Handle web search if enabled
1522
- if web_search_enabled and search_client:
1523
  search_keywords = ["날씨", "기온", "비", "눈", "뉴스", "소식", "현재", "최근",
1524
  "오늘", "지금", "가격", "환율", "주가", "weather", "news",
1525
  "current", "today", "price", "2024", "2025"]
@@ -1729,24 +1746,53 @@ IMPORTANT: Give only ONE response per user input. Do not repeat yourself or give
1729
  "voice": "alloy"
1730
  }
1731
 
1732
- await conn.session.update(session=session_update)
1733
- self.connection = conn
1734
- print(f"Connected with tools: {len(tools)} functions")
 
 
 
 
 
1735
 
1736
  async for event in self.connection:
1737
- # Handle user transcription for stop detection
1738
- if event.type == "conversation.item.created":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1739
  if hasattr(event, 'item') and hasattr(event.item, 'role') and event.item.role == "user":
1740
  if hasattr(event.item, 'content') and event.item.content:
1741
  for content_item in event.item.content:
1742
- if hasattr(content_item, 'transcript'):
1743
  user_text = content_item.transcript.lower()
1744
  stop_words = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"]
1745
 
1746
  if any(word in user_text for word in stop_words):
1747
  print(f"[STOP DETECTED] User said: {content_item.transcript}")
1748
  self.should_stop = True
1749
- # Cancel any ongoing response
1750
  if self.connection:
1751
  try:
1752
  await self.connection.response.cancel()
@@ -1758,25 +1804,25 @@ IMPORTANT: Give only ONE response per user input. Do not repeat yourself or give
1758
  if self.session_id:
1759
  await PersonalAssistantDB.save_message(self.session_id, "user", content_item.transcript)
1760
 
1761
- if event.type == "response.audio_transcript.done":
1762
  # Prevent multiple responses
1763
  if self.is_responding:
1764
  print("[DUPLICATE RESPONSE] Skipping duplicate response")
1765
  continue
1766
 
1767
  self.is_responding = True
1768
- print(f"[RESPONSE] Transcript: {event.transcript[:100]}...")
1769
 
1770
  # Detect language
1771
  detected_language = None
1772
  try:
1773
  if event.transcript and len(event.transcript) > 10:
1774
  detected_language = detect(event.transcript)
1775
- except:
1776
- pass
1777
 
1778
  # Save to database
1779
- if self.session_id:
1780
  await PersonalAssistantDB.save_message(self.session_id, "assistant", event.transcript)
1781
 
1782
  output_data = {
@@ -1796,14 +1842,20 @@ IMPORTANT: Give only ONE response per user input. Do not repeat yourself or give
1796
  if self.should_stop:
1797
  continue
1798
 
1799
- await self.output_queue.put(
1800
- (
1801
- self.output_sample_rate,
1802
- np.frombuffer(
1803
- base64.b64decode(event.delta), dtype=np.int16
1804
- ).reshape(1, -1),
1805
- ),
1806
- )
 
 
 
 
 
 
1807
 
1808
  # Handle function calls
1809
  elif event.type == "response.function_call_arguments.start":
@@ -1856,7 +1908,15 @@ IMPORTANT: Give only ONE response per user input. Do not repeat yourself or give
1856
  print(f"[RECEIVE] No connection, skipping")
1857
  return
1858
  try:
 
 
 
 
1859
  _, array = frame
 
 
 
 
1860
  array = array.squeeze()
1861
  audio_message = base64.b64encode(array.tobytes()).decode("utf-8")
1862
  await self.connection.input_audio_buffer.append(audio=audio_message)
@@ -1908,20 +1968,26 @@ stream.mount(app)
1908
  # Initialize database on startup
1909
  @app.on_event("startup")
1910
  async def startup_event():
1911
- await PersonalAssistantDB.init()
1912
- print(f"Database initialized at: {DB_PATH}")
1913
- print(f"Persistent directory: {PERSISTENT_DIR}")
1914
- print(f"DB file exists: {os.path.exists(DB_PATH)}")
1915
-
1916
- # Check if we're in Hugging Face Space
1917
- if os.path.exists("/data"):
1918
- print("Running in Hugging Face Space with persistent storage")
1919
- # List files in persistent directory
1920
- try:
1921
- files = os.listdir(PERSISTENT_DIR)
1922
- print(f"Files in persistent directory: {files}")
1923
- except Exception as e:
1924
- print(f"Error listing files: {e}")
 
 
 
 
 
 
1925
 
1926
  # Intercept offer to capture settings
1927
  @app.post("/webrtc/offer", include_in_schema=False)
 
755
  const message = textInput.value.trim();
756
  if (!message) return;
757
 
758
+ // Check for stop words
759
+ const stopWords = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"];
760
+ if (stopWords.some(word => message.toLowerCase().includes(word))) {
761
+ addMessage('assistant', '대화를 중단합니다.');
762
+ return;
763
+ }
764
+
765
  // Add user message to chat
766
  addMessage('user', message);
767
  textInput.value = '';
 
1253
  @staticmethod
1254
  async def save_message(session_id: str, role: str, content: str):
1255
  """Save a message to the database"""
1256
+ # Check for None or empty content
1257
+ if not content:
1258
+ print(f"[SAVE_MESSAGE] Empty content for {role} message, skipping")
1259
+ return
1260
+
1261
  # Detect language
1262
  detected_language = None
1263
  try:
1264
  if content and len(content) > 10:
1265
  detected_language = detect(content)
1266
+ except (LangDetectException, Exception) as e:
1267
+ print(f"Language detection error: {e}")
1268
 
1269
  async with aiosqlite.connect(DB_PATH) as db:
1270
  await db.execute(
 
1402
  # Prepare conversation text for analysis
1403
  conversation_text = "\n".join([
1404
  f"{msg['role']}: {msg['content']}"
1405
+ for msg in messages if msg.get('content')
1406
  ])
1407
 
1408
  # Use GPT to extract memories
 
1496
 
1497
  memory_text = "\n\n=== 기억된 정보 ===\n"
1498
  for category, items in memories.items():
1499
+ if items and isinstance(items, list):
1500
  memory_text += f"\n[{category}]\n"
1501
  for item in items:
1502
+ if item: # Check if item is not None or empty
1503
+ memory_text += f"- {item}\n"
1504
 
1505
  return memory_text
1506
 
 
1509
  user_name: str = "", memories: Dict = None) -> Dict[str, str]:
1510
  """Process text chat using GPT-4o-mini model"""
1511
  try:
1512
+ # Check for empty or None message
1513
+ if not message:
1514
+ return {"error": "메시지가 비어있습니다."}
1515
+
1516
  # Check for stop words
1517
  stop_words = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"]
1518
  if any(word in message.lower() for word in stop_words):
 
1536
  messages = [{"role": "system", "content": base_prompt}]
1537
 
1538
  # Handle web search if enabled
1539
+ if web_search_enabled and search_client and message:
1540
  search_keywords = ["날씨", "기온", "비", "눈", "뉴스", "소식", "현재", "최근",
1541
  "오늘", "지금", "가격", "환율", "주가", "weather", "news",
1542
  "current", "today", "price", "2024", "2025"]
 
1746
  "voice": "alloy"
1747
  }
1748
 
1749
+ try:
1750
+ await conn.session.update(session=session_update)
1751
+ self.connection = conn
1752
+ print(f"Connected with tools: {len(tools)} functions")
1753
+ print(f"Session update successful")
1754
+ except Exception as e:
1755
+ print(f"Error updating session: {e}")
1756
+ raise
1757
 
1758
  async for event in self.connection:
1759
+ # Debug log for all events
1760
+ if hasattr(event, 'type'):
1761
+ if event.type not in ["response.audio.delta", "response.audio.done"]:
1762
+ print(f"[EVENT] Type: {event.type}")
1763
+
1764
+ # Handle user input audio transcription
1765
+ if event.type == "conversation.item.input_audio_transcription.completed":
1766
+ if hasattr(event, 'transcript') and event.transcript:
1767
+ user_text = event.transcript.lower()
1768
+ stop_words = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"]
1769
+
1770
+ if any(word in user_text for word in stop_words):
1771
+ print(f"[STOP DETECTED] User said: {event.transcript}")
1772
+ self.should_stop = True
1773
+ if self.connection:
1774
+ try:
1775
+ await self.connection.response.cancel()
1776
+ except:
1777
+ pass
1778
+ continue
1779
+
1780
+ # Save user message to database
1781
+ if self.session_id:
1782
+ await PersonalAssistantDB.save_message(self.session_id, "user", event.transcript)
1783
+
1784
+ # Handle user transcription for stop detection (alternative event)
1785
+ elif event.type == "conversation.item.created":
1786
  if hasattr(event, 'item') and hasattr(event.item, 'role') and event.item.role == "user":
1787
  if hasattr(event.item, 'content') and event.item.content:
1788
  for content_item in event.item.content:
1789
+ if hasattr(content_item, 'transcript') and content_item.transcript:
1790
  user_text = content_item.transcript.lower()
1791
  stop_words = ["중단", "그만", "스톱", "stop", "닥쳐", "멈춰", "중지"]
1792
 
1793
  if any(word in user_text for word in stop_words):
1794
  print(f"[STOP DETECTED] User said: {content_item.transcript}")
1795
  self.should_stop = True
 
1796
  if self.connection:
1797
  try:
1798
  await self.connection.response.cancel()
 
1804
  if self.session_id:
1805
  await PersonalAssistantDB.save_message(self.session_id, "user", content_item.transcript)
1806
 
1807
+ elif event.type == "response.audio_transcript.done":
1808
  # Prevent multiple responses
1809
  if self.is_responding:
1810
  print("[DUPLICATE RESPONSE] Skipping duplicate response")
1811
  continue
1812
 
1813
  self.is_responding = True
1814
+ print(f"[RESPONSE] Transcript: {event.transcript[:100] if event.transcript else 'None'}...")
1815
 
1816
  # Detect language
1817
  detected_language = None
1818
  try:
1819
  if event.transcript and len(event.transcript) > 10:
1820
  detected_language = detect(event.transcript)
1821
+ except Exception as e:
1822
+ print(f"Language detection error: {e}")
1823
 
1824
  # Save to database
1825
+ if self.session_id and event.transcript:
1826
  await PersonalAssistantDB.save_message(self.session_id, "assistant", event.transcript)
1827
 
1828
  output_data = {
 
1842
  if self.should_stop:
1843
  continue
1844
 
1845
+ if hasattr(event, 'delta'):
1846
+ await self.output_queue.put(
1847
+ (
1848
+ self.output_sample_rate,
1849
+ np.frombuffer(
1850
+ base64.b64decode(event.delta), dtype=np.int16
1851
+ ).reshape(1, -1),
1852
+ ),
1853
+ )
1854
+
1855
+ # Handle errors
1856
+ elif event.type == "error":
1857
+ print(f"[ERROR] {event}")
1858
+ self.is_responding = False
1859
 
1860
  # Handle function calls
1861
  elif event.type == "response.function_call_arguments.start":
 
1908
  print(f"[RECEIVE] No connection, skipping")
1909
  return
1910
  try:
1911
+ if frame is None or len(frame) < 2:
1912
+ print(f"[RECEIVE] Invalid frame")
1913
+ return
1914
+
1915
  _, array = frame
1916
+ if array is None:
1917
+ print(f"[RECEIVE] Null array")
1918
+ return
1919
+
1920
  array = array.squeeze()
1921
  audio_message = base64.b64encode(array.tobytes()).decode("utf-8")
1922
  await self.connection.input_audio_buffer.append(audio=audio_message)
 
1968
  # Initialize database on startup
1969
  @app.on_event("startup")
1970
  async def startup_event():
1971
+ try:
1972
+ await PersonalAssistantDB.init()
1973
+ print(f"Database initialized at: {DB_PATH}")
1974
+ print(f"Persistent directory: {PERSISTENT_DIR}")
1975
+ print(f"DB file exists: {os.path.exists(DB_PATH)}")
1976
+
1977
+ # Check if we're in Hugging Face Space
1978
+ if os.path.exists("/data"):
1979
+ print("Running in Hugging Face Space with persistent storage")
1980
+ # List files in persistent directory
1981
+ try:
1982
+ files = os.listdir(PERSISTENT_DIR)
1983
+ print(f"Files in persistent directory: {files}")
1984
+ except Exception as e:
1985
+ print(f"Error listing files: {e}")
1986
+ except Exception as e:
1987
+ print(f"Error during startup: {e}")
1988
+ # Try to create directory if it doesn't exist
1989
+ os.makedirs(PERSISTENT_DIR, exist_ok=True)
1990
+ await PersonalAssistantDB.init()
1991
 
1992
  # Intercept offer to capture settings
1993
  @app.post("/webrtc/offer", include_in_schema=False)