cevheri commited on
Commit
3089d42
·
1 Parent(s): 386397f

chore: gradio interface enhancement

Browse files
Files changed (3) hide show
  1. gradio_chatbot.py +190 -113
  2. main.py +7 -1
  3. run.sh +7 -23
gradio_chatbot.py CHANGED
@@ -2,138 +2,215 @@ import gradio as gr
2
  import environs
3
  import httpx
4
  import asyncio
5
- from typing import List, Tuple
 
 
6
 
 
7
  env = environs.Env()
8
  env.read_env()
9
 
 
10
  BASE_URL = env.str("BASE_URL", "http://localhost:7860")
11
  API_KEY = env.str("API_KEY", "sk-test-xxx")
12
  CHAT_API_ENDPOINT = f"{BASE_URL}/v1/chat/completions"
13
 
14
- async def call_chat_api(prompt: str) -> Tuple[str, str]:
15
- print(f"Calling chat API with prompt: {prompt}")
16
- try:
17
- async with httpx.AsyncClient() as client:
18
- response = await client.post(
19
- CHAT_API_ENDPOINT,
20
- headers={"Authorization": f"Bearer {API_KEY}"},
21
- json={
22
- "messages": [{"role": "user", "content": prompt}],
23
- "model": "gpt-3.5-turbo",
24
- "completion_id": "new_chat",
25
- "stream": True
26
- }
27
- )
28
-
29
- if response.status_code != 200:
30
- print(f"Error response: {response.text}")
31
- return "Error", f"API Error: {response.text}"
32
-
33
- result = response.json()
34
- print(f"API response: {result}")
35
-
36
- if "choices" in result and len(result["choices"]) > 0:
37
- message = result["choices"][0].get("message", {})
38
- content = message.get("content", "Content not found")
39
- print(f"Last message: {content}")
40
- return "Success", content
41
- else:
42
- return "Error", "Invalid API response"
43
-
44
- except Exception as e:
45
- print(f"Error: {str(e)}")
46
- return "Error", f"Error: {str(e)}"
47
 
48
- def build_gradio_app():
49
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
50
- gr.Markdown("""
51
- # 🤖 Data Chatbot
52
-
53
- This chatbot allows you to chat with your data and visualize it.
54
- Please enter your question in the text box below and click the "Send" button.
55
- """)
 
 
 
 
 
 
 
 
 
 
56
 
57
- with gr.Row():
58
- with gr.Column(scale=4):
59
- chatbot = gr.Chatbot(
60
- label="Chat History",
61
- height=400,
62
- show_copy_button=True,
63
- avatar_images=("👤", "🤖")
 
 
 
 
 
 
 
 
 
 
 
64
  )
65
 
66
- with gr.Row():
67
- msg = gr.Textbox(
68
- label="Your Message",
69
- placeholder="Enter your question here...",
70
- lines=3,
71
- scale=4
72
  )
73
- submit_btn = gr.Button("Send", variant="primary", scale=1)
74
 
75
- with gr.Row():
76
- clear_btn = gr.Button("Clear Chat", variant="secondary")
77
- retry_btn = gr.Button("Retry", variant="secondary")
78
 
79
- status = gr.Textbox(label="Status", interactive=False)
80
- last_message = gr.Textbox(label="Last Message", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- async def user_message(message: str, history: List[List[str]]) -> Tuple[List[List[str]], str, str, str]:
83
- if not message.strip():
84
- return history, "", "Please enter a message.", ""
 
 
 
 
85
 
86
- history.append([message, ""])
87
- status_text, response = await call_chat_api(message)
88
 
89
- if status_text == "Success":
90
- history[-1][1] = response
91
- return history, "", "Message sent successfully.", response
92
- else:
93
- history[-1][1] = f"❌ {response}"
94
- return history, "", f"Error: {response}", ""
95
-
96
- def clear_history() -> Tuple[List[List[str]], str, str, str]:
97
- return [], "", "Chat cleared.", ""
98
-
99
- def retry_last_message(history: List[List[str]]) -> Tuple[List[List[str]], str, str, str]:
100
- if not history:
101
- return history, "", "No message to retry.", ""
102
 
103
- last_message = history[-1][0]
104
- return history[:-1], last_message, "Last message will be retried.", ""
105
-
106
- submit_btn.click(
107
- fn=user_message,
108
- inputs=[msg, chatbot],
109
- outputs=[chatbot, msg, status, last_message]
110
- )
111
-
112
- msg.submit(
113
- fn=user_message,
114
- inputs=[msg, chatbot],
115
- outputs=[chatbot, msg, status, last_message]
116
- )
117
-
118
- clear_btn.click(
119
- fn=clear_history,
120
- inputs=[],
121
- outputs=[chatbot, msg, status, last_message]
122
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- retry_btn.click(
125
- fn=retry_last_message,
126
- inputs=[chatbot],
127
- outputs=[chatbot, msg, status, last_message]
128
- )
129
 
130
- return demo
 
 
 
 
 
 
 
 
 
131
 
132
- if __name__ == "__main__":
133
- demo = build_gradio_app()
134
- demo.launch(
135
- server_name="0.0.0.0",
136
- server_port=7861,
137
- share=False,
138
- show_error=True
139
- )
 
2
  import environs
3
  import httpx
4
  import asyncio
5
+ from typing import List, Tuple, Dict, Optional
6
+ from dataclasses import dataclass
7
+ from enum import Enum
8
 
9
+ # Environment configuration
10
  env = environs.Env()
11
  env.read_env()
12
 
13
+ # API Configuration
14
  BASE_URL = env.str("BASE_URL", "http://localhost:7860")
15
  API_KEY = env.str("API_KEY", "sk-test-xxx")
16
  CHAT_API_ENDPOINT = f"{BASE_URL}/v1/chat/completions"
17
 
18
+ class MessageStatus(Enum):
19
+ """Enum for message status"""
20
+ SUCCESS = "Success"
21
+ ERROR = "Error"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ @dataclass
24
+ class MessageResponse:
25
+ """Data class for message response"""
26
+ status: MessageStatus
27
+ content: str
28
+ error: Optional[str] = None
29
+
30
+ class ChatAPI:
31
+ """Class to handle chat API interactions"""
32
+
33
+ def __init__(self, base_url: str, api_key: str):
34
+ self.base_url = base_url
35
+ self.api_key = api_key
36
+ self.endpoint = f"{base_url}/v1/chat/completions"
37
+
38
+ async def send_message(self, prompt: str) -> MessageResponse:
39
+ """
40
+ Send a message to the chat API
41
 
42
+ Args:
43
+ prompt (str): The message to send
44
+
45
+ Returns:
46
+ MessageResponse: The response from the API
47
+ """
48
+ print(f"Calling chat API with prompt: {prompt}")
49
+ try:
50
+ async with httpx.AsyncClient() as client:
51
+ response = await client.post(
52
+ self.endpoint,
53
+ headers={"Authorization": f"Bearer {self.api_key}"},
54
+ json={
55
+ "messages": [{"role": "user", "content": prompt}],
56
+ "model": "gpt-3.5-turbo",
57
+ "completion_id": "new_chat",
58
+ "stream": True
59
+ }
60
  )
61
 
62
+ if response.status_code != 200:
63
+ print(f"Error response: {response.text}")
64
+ return MessageResponse(
65
+ status=MessageStatus.ERROR,
66
+ content="",
67
+ error=f"API Error: {response.text}"
68
  )
 
69
 
70
+ result = response.json()
71
+ print(f"API response: {result}")
 
72
 
73
+ if "choices" in result and len(result["choices"]) > 0:
74
+ message = result["choices"][0].get("message", {})
75
+ content = message.get("content", "Content not found")
76
+ print(f"Last message: {content}")
77
+ return MessageResponse(
78
+ status=MessageStatus.SUCCESS,
79
+ content=content
80
+ )
81
+ else:
82
+ return MessageResponse(
83
+ status=MessageStatus.ERROR,
84
+ content="",
85
+ error="Invalid API response"
86
+ )
87
+
88
+ except Exception as e:
89
+ print(f"Error: {str(e)}")
90
+ return MessageResponse(
91
+ status=MessageStatus.ERROR,
92
+ content="",
93
+ error=f"Error: {str(e)}"
94
+ )
95
+
96
+ class ChatInterface:
97
+ """Class to handle the Gradio chat interface"""
98
+
99
+ def __init__(self, chat_api: ChatAPI):
100
+ self.chat_api = chat_api
101
+ self.demo = self._build_interface()
102
+
103
+ def _build_interface(self) -> gr.Blocks:
104
+ """
105
+ Build the Gradio interface
106
 
107
+ Returns:
108
+ gr.Blocks: The Gradio interface
109
+ """
110
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
111
+ # Header
112
+ gr.Markdown(f"""
113
+ # 🤖 Data Chatbot
114
 
115
+ This chatbot allows you to chat with your data and visualize it.
116
+ Please enter your question in the text box below and click the "Send" button.
117
 
118
+ > 📚 API Documentation: [{self.chat_api.base_url}/docs]({self.chat_api.base_url}/docs)
119
+ """)
 
 
 
 
 
 
 
 
 
 
 
120
 
121
+ # Main chat interface
122
+ with gr.Row():
123
+ with gr.Column(scale=4):
124
+ # Chat history display
125
+ chatbot = gr.Chatbot(
126
+ label="Chat History",
127
+ height=400,
128
+ show_copy_button=True,
129
+ avatar_images=("👤", "🤖")
130
+ )
131
+
132
+ # Message input area
133
+ with gr.Row():
134
+ msg = gr.Textbox(
135
+ label="Your Message",
136
+ placeholder="Enter your question here...",
137
+ lines=3,
138
+ scale=4
139
+ )
140
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
141
+
142
+ # Control buttons
143
+ with gr.Row():
144
+ clear_btn = gr.Button("Clear Chat", variant="secondary")
145
+ retry_btn = gr.Button("Retry", variant="secondary")
146
+
147
+ # Status and last message display
148
+ status = gr.Textbox(label="Status", interactive=False)
149
+ last_message = gr.Textbox(label="Last Message", interactive=False)
150
+
151
+ # Event handlers
152
+ async def user_message(message: str, history: List[List[str]]) -> Tuple[List[List[str]], str, str, str]:
153
+ """Handle user message submission"""
154
+ if not message.strip():
155
+ return history, "", "Please enter a message.", ""
156
+
157
+ history.append([message, ""])
158
+ response = await self.chat_api.send_message(message)
159
+
160
+ if response.status == MessageStatus.SUCCESS:
161
+ history[-1][1] = response.content
162
+ return history, "", "Message sent successfully.", response.content
163
+ else:
164
+ history[-1][1] = f"❌ {response.error}"
165
+ return history, "", f"Error: {response.error}", ""
166
+
167
+ def clear_history() -> Tuple[List[List[str]], str, str, str]:
168
+ """Clear chat history"""
169
+ return [], "", "Chat cleared.", ""
170
+
171
+ def retry_last_message(history: List[List[str]]) -> Tuple[List[List[str]], str, str, str]:
172
+ """Retry the last message"""
173
+ if not history:
174
+ return history, "", "No message to retry.", ""
175
+
176
+ last_message = history[-1][0]
177
+ return history[:-1], last_message, "Last message will be retried.", ""
178
+
179
+ # Connect event handlers to UI elements
180
+ submit_btn.click(
181
+ fn=user_message,
182
+ inputs=[msg, chatbot],
183
+ outputs=[chatbot, msg, status, last_message]
184
+ )
185
+
186
+ msg.submit(
187
+ fn=user_message,
188
+ inputs=[msg, chatbot],
189
+ outputs=[chatbot, msg, status, last_message]
190
+ )
191
+
192
+ clear_btn.click(
193
+ fn=clear_history,
194
+ inputs=[],
195
+ outputs=[chatbot, msg, status, last_message]
196
+ )
197
+
198
+ retry_btn.click(
199
+ fn=retry_last_message,
200
+ inputs=[chatbot],
201
+ outputs=[chatbot, msg, status, last_message]
202
+ )
203
 
204
+ return demo
 
 
 
 
205
 
206
+ def build_gradio_app() -> gr.Blocks:
207
+ """
208
+ Build and return the Gradio application
209
+
210
+ Returns:
211
+ gr.Blocks: The Gradio interface
212
+ """
213
+ chat_api = ChatAPI(BASE_URL, API_KEY)
214
+ chat_interface = ChatInterface(chat_api)
215
+ return chat_interface.demo
216
 
 
 
 
 
 
 
 
 
main.py CHANGED
@@ -7,6 +7,8 @@ from loguru import logger
7
  from environs import Env
8
  from contextlib import asynccontextmanager
9
  from app.db.client import mongodb
 
 
10
 
11
  print(log_config.get_log_level())
12
 
@@ -91,8 +93,12 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
91
  app.mount("/.well-known", StaticFiles(directory=".well-known"), name="well-known")
92
  app.include_router(chat_api.router)
93
 
 
 
 
 
94
  @app.get("/")
95
  async def root():
96
- return RedirectResponse(url="http://localhost:7861")
97
 
98
  # uv run uvicorn main:app --host 0.0.0.0 --port 7860 --reload
 
7
  from environs import Env
8
  from contextlib import asynccontextmanager
9
  from app.db.client import mongodb
10
+ from gradio_chatbot import build_gradio_app
11
+ import gradio as gr
12
 
13
  print(log_config.get_log_level())
14
 
 
93
  app.mount("/.well-known", StaticFiles(directory=".well-known"), name="well-known")
94
  app.include_router(chat_api.router)
95
 
96
+ # gradio mount in fastapi app
97
+ demo = build_gradio_app()
98
+ app = gr.mount_gradio_app(app, demo, path="/ui")
99
+
100
  @app.get("/")
101
  async def root():
102
+ return RedirectResponse(url="http://localhost:7860/ui")
103
 
104
  # uv run uvicorn main:app --host 0.0.0.0 --port 7860 --reload
run.sh CHANGED
@@ -1,34 +1,18 @@
1
  #!/bin/bash
2
 
3
- # Önce eski uygulamaları durdur
4
- echo "Stopping existing applications..."
5
  pkill -f "uvicorn main:app"
6
- pkill -f "python gradio_chatbot.py"
7
 
8
  # 2 saniye bekle
9
  sleep 2
10
 
11
- # FastAPI uygulamasını arka planda başlat
12
- echo "Starting FastAPI application..."
13
- uv run uvicorn main:app --host 0.0.0.0 --port 7860 --reload &
14
- FASTAPI_PID=$!
15
-
16
- # 5 saniye bekle (FastAPI'nin başlaması için)
17
- sleep 5
18
-
19
- # Gradio uygulamasını başlat
20
- echo "Starting Gradio application..."
21
- uv run python gradio_chatbot.py &
22
- GRADIO_PID=$!
23
-
24
- # Uygulamaların çalışmasını bekle
25
- echo "Applications are running..."
26
- echo "FastAPI: http://localhost:7860"
27
- echo "Gradio: http://localhost:7861"
28
- echo "Press Ctrl+C to stop all applications"
29
 
30
  # Ctrl+C ile durdurma işlemini yakala
31
- trap "echo 'Stopping applications...'; kill $FASTAPI_PID $GRADIO_PID; exit" INT
32
 
33
- # Uygulamaların çalışmasını bekle
34
  wait
 
1
  #!/bin/bash
2
 
3
+ # Önce eski uygulamayı durdur
4
+ echo "Stopping existing application..."
5
  pkill -f "uvicorn main:app"
 
6
 
7
  # 2 saniye bekle
8
  sleep 2
9
 
10
+ # FastAPI uygulamasını başlat (Gradio entegre edilmiş)
11
+ echo "Starting application..."
12
+ uv run uvicorn main:app --host 0.0.0.0 --port 7860 --reload
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  # Ctrl+C ile durdurma işlemini yakala
15
+ trap "echo 'Stopping application...'; pkill -f 'uvicorn main:app'; exit" INT
16
 
17
+ # Uygulamanın çalışmasını bekle
18
  wait