ibrahimlasfar commited on
Commit
7250ede
·
1 Parent(s): 379310a

Shorten short_description to meet Hugging Face metadata requirements

Browse files
Files changed (1) hide show
  1. main.py +116 -57
main.py CHANGED
@@ -1,5 +1,4 @@
1
  import os
2
- import io
3
  import logging
4
  from fastapi import FastAPI, Request
5
  from fastapi.responses import HTMLResponse, RedirectResponse
@@ -8,105 +7,166 @@ from fastapi.templating import Jinja2Templates
8
  from starlette.middleware.base import BaseHTTPMiddleware
9
  from fastapi.openapi.docs import get_swagger_ui_html
10
  import gradio as gr
11
-
12
  from api.endpoints import router as api_router
13
  from utils.generation import generate, LATEX_DELIMS
 
14
 
15
- # ================= إعداد اللوج =================
16
  logging.basicConfig(level=logging.INFO)
17
  logger = logging.getLogger(__name__)
18
 
 
19
  logger.info("Files in /app/: %s", os.listdir("/app"))
20
 
21
- # ================= مفاتيح HuggingFace =================
22
  HF_TOKEN = os.getenv("HF_TOKEN")
23
- BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN")
24
  if not HF_TOKEN:
25
  logger.error("HF_TOKEN is not set in environment variables.")
26
  raise ValueError("HF_TOKEN is required for Inference API.")
27
 
28
- # ================= إعداد Queue =================
29
  QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
30
  CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
31
 
32
- # ================= CSS =================
33
  css = """
34
- #input-row {display:flex; gap:6px; align-items:center;}
35
- #msg-box {flex:1;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  """
37
 
38
- # ================= دالة المعالجة =================
39
- def process_input(message, history, audio_input=None, file_input=None):
40
  input_type = "text"
41
- audio_data, image_data = None, None
42
-
43
- if audio_input: # 🎤 صوت
44
  input_type = "audio"
45
  with open(audio_input, "rb") as f:
46
  audio_data = f.read()
47
  message = "Transcribe this audio"
48
-
49
- elif file_input: # 📎 صورة / ملف
50
  if file_input.endswith(('.png', '.jpg', '.jpeg')):
51
  input_type = "image"
52
  with open(file_input, "rb") as f:
53
  image_data = f.read()
54
  message = f"Analyze image: {file_input}"
55
  else:
56
- input_type = "file"
57
  message = f"Analyze file: {file_input}"
58
-
59
- response_text, audio_response = "", None
 
60
  for chunk in generate(
61
  message=message,
62
  history=history,
 
 
 
 
 
63
  input_type=input_type,
64
  audio_data=audio_data,
65
  image_data=image_data
66
  ):
67
- if isinstance(chunk, bytes): # 🔊 صوت
68
  audio_response = io.BytesIO(chunk)
69
- audio_response.name = "reply.wav"
70
- else: # 📝 نص
71
  response_text += chunk
72
-
73
  yield response_text, audio_response
74
 
75
- # ================= واجهة Gradio =================
76
- with gr.Blocks(css=css, theme="gradio/soft") as chatbot_ui:
77
- chatbot = gr.Chatbot(label="MGZon Chatbot", height=700, latex_delimiters=LATEX_DELIMS)
78
- state = gr.State([])
79
-
80
- with gr.Row(elem_id="input-row"):
81
- msg = gr.Textbox(placeholder="Type your message...", elem_id="msg-box")
82
- mic = gr.Audio(sources=["microphone"], type="filepath", label="🎤", elem_classes="audio-input")
83
- file = gr.File(file_types=["image", ".pdf", ".txt"], label="📎", elem_classes="upload-button")
84
- send_btn = gr.Button("Send")
85
-
86
- voice_reply = gr.Audio(label="🔊 Voice Reply", type="filepath", autoplay=True)
87
-
88
- def user_submit(message, history):
89
- history = history + [(message, None)]
90
- return "", history
91
-
92
- msg.submit(user_submit, [msg, state], [msg, state]).then(
93
- process_input, [msg, state, mic, file], [chatbot, voice_reply]
94
- )
95
- send_btn.click(user_submit, [msg, state], [msg, state]).then(
96
- process_input, [msg, state, mic, file], [chatbot, voice_reply]
97
- )
98
-
99
- # ================= FastAPI =================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  app = FastAPI(title="MGZon Chatbot API")
101
 
102
- # ربط Gradio داخل FastAPI
103
  app = gr.mount_gradio_app(app, chatbot_ui, path="/gradio")
104
 
105
- # ملفات ثابتة + قوالب
106
  app.mount("/static", StaticFiles(directory="static"), name="static")
107
  templates = Jinja2Templates(directory="templates")
108
 
109
- # Middleware 404
110
  class NotFoundMiddleware(BaseHTTPMiddleware):
111
  async def dispatch(self, request: Request, call_next):
112
  try:
@@ -121,28 +181,27 @@ class NotFoundMiddleware(BaseHTTPMiddleware):
121
 
122
  app.add_middleware(NotFoundMiddleware)
123
 
124
- # Root
125
  @app.get("/", response_class=HTMLResponse)
126
  async def root(request: Request):
127
  return templates.TemplateResponse("index.html", {"request": request})
128
 
129
- # Docs
130
  @app.get("/docs", response_class=HTMLResponse)
131
  async def docs(request: Request):
132
  return templates.TemplateResponse("docs.html", {"request": request})
133
 
134
- # Swagger
135
  @app.get("/swagger", response_class=HTMLResponse)
136
  async def swagger_ui():
137
  return get_swagger_ui_html(openapi_url="/openapi.json", title="MGZon API Documentation")
138
 
139
- # Redirect
140
  @app.get("/launch-chatbot", response_class=RedirectResponse)
141
  async def launch_chatbot():
142
  return RedirectResponse(url="/gradio", status_code=302)
143
 
144
- # Run
145
  if __name__ == "__main__":
146
  import uvicorn
147
  uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
148
-
 
1
  import os
 
2
  import logging
3
  from fastapi import FastAPI, Request
4
  from fastapi.responses import HTMLResponse, RedirectResponse
 
7
  from starlette.middleware.base import BaseHTTPMiddleware
8
  from fastapi.openapi.docs import get_swagger_ui_html
9
  import gradio as gr
 
10
  from api.endpoints import router as api_router
11
  from utils.generation import generate, LATEX_DELIMS
12
+ import io
13
 
14
+ # إعداد التسجيل
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
+ # تحقق من الملفات في /app/
19
  logger.info("Files in /app/: %s", os.listdir("/app"))
20
 
21
+ # إعداد العميل لـ Hugging Face Inference API
22
  HF_TOKEN = os.getenv("HF_TOKEN")
23
+ BACKUP_HF_TOKEN = os.getenv("BACKUP_HF_TOKEN") # إضافة التوكن الاحتياطي
24
  if not HF_TOKEN:
25
  logger.error("HF_TOKEN is not set in environment variables.")
26
  raise ValueError("HF_TOKEN is required for Inference API.")
27
 
28
+ # إعدادات الـ queue
29
  QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
30
  CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
31
 
32
+ # إعداد CSS
33
  css = """
34
+ .gradio-container { max-width: 1200px; margin: auto; }
35
+ .chatbot { border: 1px solid #ccc; border-radius: 10px; padding: 15px; background-color: #f9f9f9; }
36
+ .input-textbox { font-size: 16px; padding: 10px; }
37
+ .upload-button::before {
38
+ content: '📷';
39
+ margin-right: 8px;
40
+ font-size: 22px;
41
+ }
42
+ .audio-input::before {
43
+ content: '🎤';
44
+ margin-right: 8px;
45
+ font-size: 22px;
46
+ }
47
+ .audio-output::before {
48
+ content: '🔊';
49
+ margin-right: 8px;
50
+ font-size: 22px;
51
+ }
52
+ .loading::after {
53
+ content: '';
54
+ display: inline-block;
55
+ width: 16px;
56
+ height: 16px;
57
+ border: 2px solid #333;
58
+ border-top-color: transparent;
59
+ border-radius: 50%;
60
+ animation: spin 1s linear infinite;
61
+ margin-left: 8px;
62
+ }
63
+ @keyframes spin {
64
+ to { transform: rotate(360deg); }
65
+ }
66
+ .output-container {
67
+ margin-top: 20px;
68
+ padding: 10px;
69
+ border: 1px solid #ddd;
70
+ border-radius: 8px;
71
+ }
72
+ .audio-output-container {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 10px;
76
+ margin-top: 10px;
77
+ }
78
  """
79
 
80
+ # دالة لمعالجة الإدخال (نص، صوت، صور، ملفات)
81
+ def process_input(message, audio_input=None, file_input=None, history=None, system_prompt=None, temperature=0.7, reasoning_effort="medium", enable_browsing=True, max_new_tokens=128000):
82
  input_type = "text"
83
+ audio_data = None
84
+ image_data = None
85
+ if audio_input:
86
  input_type = "audio"
87
  with open(audio_input, "rb") as f:
88
  audio_data = f.read()
89
  message = "Transcribe this audio"
90
+ elif file_input:
91
+ input_type = "file"
92
  if file_input.endswith(('.png', '.jpg', '.jpeg')):
93
  input_type = "image"
94
  with open(file_input, "rb") as f:
95
  image_data = f.read()
96
  message = f"Analyze image: {file_input}"
97
  else:
 
98
  message = f"Analyze file: {file_input}"
99
+
100
+ response_text = ""
101
+ audio_response = None
102
  for chunk in generate(
103
  message=message,
104
  history=history,
105
+ system_prompt=system_prompt,
106
+ temperature=temperature,
107
+ reasoning_effort=reasoning_effort,
108
+ enable_browsing=enable_browsing,
109
+ max_new_tokens=max_new_tokens,
110
  input_type=input_type,
111
  audio_data=audio_data,
112
  image_data=image_data
113
  ):
114
+ if isinstance(chunk, bytes):
115
  audio_response = io.BytesIO(chunk)
116
+ audio_response.name = "response.wav"
117
+ else:
118
  response_text += chunk
 
119
  yield response_text, audio_response
120
 
121
+ # إعداد واجهة Gradio
122
+ chatbot_ui = gr.ChatInterface(
123
+ fn=process_input,
124
+ chatbot=gr.Chatbot(
125
+ label="MGZon Chatbot",
126
+ height=800,
127
+ latex_delimiters=LATEX_DELIMS,
128
+ ),
129
+ additional_inputs_accordion=gr.Accordion("⚙️ Settings", open=True),
130
+ additional_inputs=[
131
+ gr.Textbox(
132
+ label="System Prompt",
133
+ value="You are an expert assistant providing detailed, comprehensive, and well-structured responses. Support text, audio, image, and file inputs. For audio, transcribe using Whisper. For text-to-speech, use Parler-TTS. For images and files, analyze content appropriately. Continue generating content until the query is fully addressed, leveraging the full capacity of the model.",
134
+ lines=4
135
+ ),
136
+ gr.Slider(label="Temperature", minimum=0.0, maximum=1.0, step=0.1, value=0.7),
137
+ gr.Radio(label="Reasoning Effort", choices=["low", "medium", "high"], value="medium"),
138
+ gr.Checkbox(label="Enable DeepSearch (web browsing)", value=True),
139
+ gr.Slider(label="Max New Tokens", minimum=50, maximum=128000, step=50, value=128000),
140
+ gr.Audio(label="Voice Input", type="filepath", elem_classes="audio-input"),
141
+ gr.File(label="Upload Image/File", file_types=["image", ".pdf", ".txt"], elem_classes="upload-button"),
142
+ ],
143
+ additional_outputs=[gr.Audio(label="Voice Output", type="filepath", elem_classes="audio-output", autoplay=True)],
144
+ stop_btn="Stop",
145
+ examples=[
146
+ ["Explain the difference between supervised and unsupervised learning in detail with examples."],
147
+ ["Generate a complete React component for a login form with form validation and error handling."],
148
+ ["Describe this image: https://example.com/image.jpg"],
149
+ ["Transcribe this audio: [upload audio file]."],
150
+ ["Convert this text to speech: Hello, welcome to MGZon!"],
151
+ ["Analyze this file: [upload PDF or text file]."],
152
+ ],
153
+ title="MGZon Chatbot",
154
+ description="A versatile chatbot powered by DeepSeek, CLIP, Whisper, and Parler-TTS for text, image, audio, and file queries. Supports long responses, voice input/output, file uploads with custom icons, and backup token switching. Licensed under Apache 2.0.",
155
+ theme="gradio/soft",
156
+ css=css,
157
+ )
158
+
159
+ # إعداد FastAPI
160
  app = FastAPI(title="MGZon Chatbot API")
161
 
162
+ # ربط Gradio مع FastAPI
163
  app = gr.mount_gradio_app(app, chatbot_ui, path="/gradio")
164
 
165
+ # ربط الملفات الثابتة والقوالب
166
  app.mount("/static", StaticFiles(directory="static"), name="static")
167
  templates = Jinja2Templates(directory="templates")
168
 
169
+ # Middleware لمعالجة 404
170
  class NotFoundMiddleware(BaseHTTPMiddleware):
171
  async def dispatch(self, request: Request, call_next):
172
  try:
 
181
 
182
  app.add_middleware(NotFoundMiddleware)
183
 
184
+ # Root endpoint
185
  @app.get("/", response_class=HTMLResponse)
186
  async def root(request: Request):
187
  return templates.TemplateResponse("index.html", {"request": request})
188
 
189
+ # Docs endpoint
190
  @app.get("/docs", response_class=HTMLResponse)
191
  async def docs(request: Request):
192
  return templates.TemplateResponse("docs.html", {"request": request})
193
 
194
+ # Swagger UI endpoint
195
  @app.get("/swagger", response_class=HTMLResponse)
196
  async def swagger_ui():
197
  return get_swagger_ui_html(openapi_url="/openapi.json", title="MGZon API Documentation")
198
 
199
+ # Redirect لـ /gradio
200
  @app.get("/launch-chatbot", response_class=RedirectResponse)
201
  async def launch_chatbot():
202
  return RedirectResponse(url="/gradio", status_code=302)
203
 
204
+ # تشغيل الخادم
205
  if __name__ == "__main__":
206
  import uvicorn
207
  uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))