tlong-ds commited on
Commit
01eb587
·
verified ·
1 Parent(s): fdda1a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -80
app.py CHANGED
@@ -1,135 +1,106 @@
1
  from dotenv import load_dotenv
2
  load_dotenv()
3
 
4
- import time
5
  import chainlit as cl
6
  import httpx
7
  import asyncio
8
- from typing import Optional
9
  import os
10
 
11
- API_URL = os.getenv("API_URL", "http://localhost:8000/")
12
 
 
 
 
 
13
  class ChatService:
14
- """Handles chat-related operations with async HTTP calls"""
15
-
16
  @staticmethod
17
  async def respond_to_chat(message: str) -> str:
18
- """Handle chat responses using async HTTP"""
19
-
20
  try:
21
- response = httpx.post(
22
- f"{API_URL}/chat",
23
- data={"message": message},
24
- timeout=30.0
25
- )
26
 
27
  if response.status_code == 200:
28
- print(response)
29
  raw_response = str(response.text).strip()
30
-
31
- # Unescape the response to convert \n to actual newlines
32
  if raw_response:
33
- # Remove quotes if the response is wrapped in quotes
34
  if raw_response.startswith('"') and raw_response.endswith('"'):
35
  raw_response = raw_response[1:-1]
36
-
37
- # Convert escaped characters to actual characters
38
- formatted_response = raw_response.replace('\\n', '\n').replace('\\"', '"').replace('\\*', '*')
39
-
 
 
40
  return formatted_response
41
  else:
42
  return "**No response received from the API.**"
43
  else:
44
  return f"**API Error {response.status_code}:**\n\n```\n{response.text}\n```"
45
-
46
  except Exception as e:
47
  return f"**Error:** {str(e)}"
48
 
49
- class DisplayService:
50
- """Handles display-related operations"""
51
-
52
- @staticmethod
53
- async def format_sentiment_response(sentiment_data: dict) -> str:
54
- """Format sentiment analysis response"""
55
- if not sentiment_data:
56
- return "Unable to analyze sentiment"
57
-
58
- # Format the sentiment analysis result
59
- sentiment = sentiment_data.get("sentiment", "Unknown")
60
- confidence = sentiment_data.get("confidence", 0.0)
61
-
62
- return f"**Sentiment**: {sentiment}\n**Confidence**: {confidence:.2%}"
63
-
64
-
65
- class UIService:
66
- """Handles UI-related operations"""
67
-
68
- @staticmethod
69
- async def send_message(content: str, author="assistant"):
70
- """Send a simple message"""
71
- await cl.Message(
72
- content=content,
73
- author=author
74
- ).send()
75
-
76
 
 
 
 
77
  async def run_typing_animation(msg: cl.Message):
78
- """Run typing animation until cancelled"""
79
- typing_frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
80
- frame_index = 0
81
-
82
  try:
83
- while True: # Run indefinitely until cancelled
84
- frame = typing_frames[frame_index % len(typing_frames)]
85
- msg.content = f"{frame} Analyzing sentiment..."
86
  await msg.update()
87
  await asyncio.sleep(0.25)
88
- frame_index += 1
89
-
90
  except asyncio.CancelledError:
91
- # Animation was cancelled, this is expected
92
- print("🎬 Animation cancelled - API response received")
93
  raise
94
 
 
 
 
 
95
  @cl.on_chat_start
96
  async def on_chat_start():
97
- """Initialize the chat session"""
98
  await cl.Message(
99
- content="**Sentiment Analysis**\n\n"
100
- "Hi there! 😊 I'm Sen, your friendly sentiment analysis assistant! I'm here to help you understand the emotions and feelings behind your words. Share anything with me and I'll cheerfully analyze the sentiment for you! 🌟\n\n"
101
- "Feel free to ask me about the sentiment of your text. Let's get started! 🚀",
 
 
 
 
102
  author="assistant"
103
  ).send()
104
 
105
 
106
  @cl.on_message
107
  async def main(message: cl.Message):
108
- """Main message handler with concurrent animation and API call"""
109
-
110
- # Create a placeholder message for typing animation
111
  msg = cl.Message(content="⠋ Analyzing sentiment...", author="assistant")
112
  await msg.send()
113
-
114
- # Create concurrent tasks
115
  animation_task = asyncio.create_task(run_typing_animation(msg))
116
  api_task = asyncio.create_task(ChatService.respond_to_chat(message.content))
117
-
118
  try:
119
- response = await api_task
120
- animation_task.cancel()
121
- try:
122
- await asyncio.wait_for(animation_task, timeout=0.1)
123
- except (asyncio.CancelledError, asyncio.TimeoutError):
124
- pass
125
- except Exception as e:
126
- animation_task.cancel()
127
  try:
128
  await asyncio.wait_for(animation_task, timeout=0.1)
129
  except (asyncio.CancelledError, asyncio.TimeoutError):
130
  pass
131
- response = f"Error: {e}"
132
-
133
- # Update final message
134
  msg.content = response
135
  await msg.update()
 
1
  from dotenv import load_dotenv
2
  load_dotenv()
3
 
 
4
  import chainlit as cl
5
  import httpx
6
  import asyncio
 
7
  import os
8
 
9
+ API_URL = os.getenv("API_URL", "http://localhost:8000")
10
 
11
+
12
+ # -----------------------------
13
+ # Chat Service (async HTTP calls)
14
+ # -----------------------------
15
  class ChatService:
 
 
16
  @staticmethod
17
  async def respond_to_chat(message: str) -> str:
18
+ """Send message to backend API and return formatted response"""
 
19
  try:
20
+ async with httpx.AsyncClient(timeout=30.0) as client:
21
+ response = await client.post(
22
+ f"{API_URL}/chat",
23
+ data={"message": message}
24
+ )
25
 
26
  if response.status_code == 200:
 
27
  raw_response = str(response.text).strip()
28
+
 
29
  if raw_response:
 
30
  if raw_response.startswith('"') and raw_response.endswith('"'):
31
  raw_response = raw_response[1:-1]
32
+
33
+ formatted_response = (
34
+ raw_response.replace("\\n", "\n")
35
+ .replace('\\"', '"')
36
+ .replace("\\*", "*")
37
+ )
38
  return formatted_response
39
  else:
40
  return "**No response received from the API.**"
41
  else:
42
  return f"**API Error {response.status_code}:**\n\n```\n{response.text}\n```"
43
+
44
  except Exception as e:
45
  return f"**Error:** {str(e)}"
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # -----------------------------
49
+ # Typing animation
50
+ # -----------------------------
51
  async def run_typing_animation(msg: cl.Message):
52
+ frames = ["", "⠙", "⠹", "⠸", "⠼", "", "⠦", "⠧", "⠇", "⠏"]
53
+ idx = 0
 
 
54
  try:
55
+ while True:
56
+ msg.content = f"{frames[idx % len(frames)]} Analyzing sentiment..."
 
57
  await msg.update()
58
  await asyncio.sleep(0.25)
59
+ idx += 1
 
60
  except asyncio.CancelledError:
61
+ # Expected when we cancel after API finishes
 
62
  raise
63
 
64
+
65
+ # -----------------------------
66
+ # Chainlit Handlers
67
+ # -----------------------------
68
  @cl.on_chat_start
69
  async def on_chat_start():
70
+ """Show intro message when chat starts"""
71
  await cl.Message(
72
+ content=(
73
+ "**Sentiment Analysis**\n\n"
74
+ "Hi there! 😊 I'm Sen, your friendly sentiment analysis assistant! "
75
+ "I'm here to help you understand the emotions and feelings behind your words. "
76
+ "Share anything with me and I'll cheerfully analyze the sentiment for you! 🌟\n\n"
77
+ "Feel free to ask me about the sentiment of your text. Let's get started! 🚀"
78
+ ),
79
  author="assistant"
80
  ).send()
81
 
82
 
83
  @cl.on_message
84
  async def main(message: cl.Message):
85
+ """Handle user messages with animation + API call"""
86
+
87
+ # Placeholder message (starts typing animation)
88
  msg = cl.Message(content="⠋ Analyzing sentiment...", author="assistant")
89
  await msg.send()
90
+
91
+ # Run animation + API call concurrently
92
  animation_task = asyncio.create_task(run_typing_animation(msg))
93
  api_task = asyncio.create_task(ChatService.respond_to_chat(message.content))
94
+
95
  try:
96
+ response = await api_task # wait for API result
97
+ finally:
98
+ animation_task.cancel() # stop animation
 
 
 
 
 
99
  try:
100
  await asyncio.wait_for(animation_task, timeout=0.1)
101
  except (asyncio.CancelledError, asyncio.TimeoutError):
102
  pass
103
+
104
+ # Update final content
 
105
  msg.content = response
106
  await msg.update()