MGZON commited on
Commit
d2a410a
·
1 Parent(s): 5f2ba28

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +136 -28
app/main.py CHANGED
@@ -5,6 +5,9 @@ import gradio as gr
5
  from openai import OpenAI
6
  from pydoc import html
7
  from typing import List, Generator, Optional
 
 
 
8
 
9
  # تعريف LATEX_DELIMS
10
  LATEX_DELIMS = [
@@ -25,6 +28,7 @@ logger.info("Files in /app/: %s", os.listdir("/app"))
25
  HF_TOKEN = os.getenv("HF_TOKEN")
26
  API_ENDPOINT = os.getenv("API_ENDPOINT", "https://api-inference.huggingface.co/v1")
27
  MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:cerebras")
 
28
  if not HF_TOKEN:
29
  logger.error("HF_TOKEN is not set in environment variables.")
30
  raise ValueError("HF_TOKEN is required for Inference API.")
@@ -34,7 +38,63 @@ client = OpenAI(api_key=HF_TOKEN, base_url=API_ENDPOINT)
34
  QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
35
  CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
36
 
37
- # دالة request_generation (دمج من gateway.py)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  def request_generation(
39
  api_key: str,
40
  api_base: str,
@@ -42,11 +102,12 @@ def request_generation(
42
  system_prompt: str,
43
  model_name: str,
44
  chat_history: Optional[List[dict]] = None,
45
- temperature: float = 0.3,
46
- max_new_tokens: int = 1024,
47
  reasoning_effort: str = "off",
48
  tools: Optional[List[dict]] = None,
49
  tool_choice: Optional[str] = None,
 
50
  ) -> Generator[str, None, None]:
51
  """Streams Responses API events. Emits:
52
  - "analysis" sentinel once, then raw reasoning deltas
@@ -54,18 +115,43 @@ def request_generation(
54
  If no visible deltas, emits a tool-call fallback message."""
55
  client = OpenAI(api_key=api_key, base_url=api_base)
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  # تنظيف الـ messages من metadata
58
- input_messages: List[dict] = [{"role": "system", "content": system_prompt}]
59
  if chat_history:
60
  for msg in chat_history:
61
  clean_msg = {"role": msg.get("role"), "content": msg.get("content")}
62
  if clean_msg["content"]:
63
  input_messages.append(clean_msg)
64
- input_messages.append({"role": "user", "content": message})
65
-
66
- # إعداد tools و tool_choice
67
- tools = tools if tools else []
68
- tool_choice = tool_choice if tool_choice in ["auto", "none", "any", "required"] else "none"
 
 
 
 
 
 
69
 
70
  try:
71
  stream = client.chat.completions.create(
@@ -107,7 +193,7 @@ def request_generation(
107
  buffer = ""
108
  continue
109
 
110
- if chunk.choices[0].delta.tool_calls:
111
  tool_call = chunk.choices[0].delta.tool_calls[0]
112
  name = getattr(tool_call, "function", {}).get("name", None)
113
  args = getattr(tool_call, "function", {}).get("arguments", None)
@@ -167,6 +253,9 @@ def generate(message, history, system_prompt, temperature, reasoning_effort, ena
167
  yield "Please enter a prompt."
168
  return
169
 
 
 
 
170
  # Flatten gradio history وتنظيف metadata
171
  chat_history = []
172
  for h in history:
@@ -179,22 +268,38 @@ def generate(message, history, system_prompt, temperature, reasoning_effort, ena
179
  if u: chat_history.append({"role": "user", "content": u})
180
  if a: chat_history.append({"role": "assistant", "content": a})
181
 
182
- # إعداد الأدوات إذا تم تفعيل البحث على الويب
183
  tools = [
184
  {
185
  "type": "function",
186
  "function": {
187
  "name": "web_search_preview",
188
- "description": "Simulate web search for additional context",
189
  "parameters": {
190
  "type": "object",
191
  "properties": {"query": {"type": "string", "description": "Search query"}},
192
  "required": ["query"],
193
  },
194
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  }
196
- ] if enable_browsing else []
197
- tool_choice = "auto" if enable_browsing else "none"
198
 
199
  in_analysis = False
200
  in_visible = False
@@ -220,12 +325,13 @@ def generate(message, history, system_prompt, temperature, reasoning_effort, ena
220
  api_base=API_ENDPOINT,
221
  message=message,
222
  system_prompt=system_prompt,
223
- model_name=MODEL_NAME,
224
  chat_history=chat_history,
225
  temperature=temperature,
226
  max_new_tokens=max_new_tokens,
227
  tools=tools,
228
  tool_choice=tool_choice,
 
229
  )
230
 
231
  for chunk in stream:
@@ -275,30 +381,32 @@ chatbot_ui = gr.ChatInterface(
275
  fn=generate,
276
  type="messages",
277
  chatbot=gr.Chatbot(
278
- label="MGZon-120B Chatbot",
279
  type="messages",
280
  height=600,
281
  latex_delimiters=LATEX_DELIMS,
282
  ),
283
  additional_inputs_accordion=gr.Accordion("⚙️ Settings", open=True),
284
  additional_inputs=[
285
- gr.Textbox(label="System prompt", value="You are a helpful assistant.", lines=2),
286
- gr.Slider(label="Temperature", minimum=0.0, maximum=1.0, step=0.1, value=0.7),
287
  gr.Radio(label="Reasoning Effort", choices=["low", "medium", "high"], value="medium"),
288
- gr.Checkbox(label="Enable web browsing (simulated)", value=False),
289
- gr.Slider(label="Max New Tokens", minimum=50, maximum=1024, step=50, value=200),
290
  ],
291
  stop_btn="Stop",
292
  examples=[
293
  ["Explain the difference between supervised and unsupervised learning."],
294
- ["Summarize the plot of Inception in two sentences."],
295
- ["Show me the LaTeX for the quadratic formula."],
296
- ["What are advantages of AMD Instinct MI300X GPU?"],
297
- ["Derive the gradient of softmax cross-entropy loss."],
298
- ["Explain why ∂/∂x xⁿ = n·xⁿ⁻¹ holds."],
 
 
299
  ],
300
- title="MGZon-120B Chatbot on Hugging Face",
301
- description="This Space demonstrates the GPT-MGZon-120B model running via Hugging Face Inference API. Includes analysis for chain of thought insights. Licensed under Apache 2.0. ***DISCLAIMER:*** Analysis may contain internal thoughts not suitable for final response.",
302
  theme="gradio/soft",
303
  css=css,
304
  )
@@ -307,7 +415,7 @@ chatbot_ui = gr.ChatInterface(
307
  from fastapi import FastAPI
308
  from gradio import mount_gradio_app
309
 
310
- app = FastAPI(title="MGZon-120B API")
311
  app = mount_gradio_app(app, chatbot_ui, path="/")
312
 
313
  # تشغيل الخادم
 
5
  from openai import OpenAI
6
  from pydoc import html
7
  from typing import List, Generator, Optional
8
+ import requests
9
+ from bs4 import BeautifulSoup
10
+ import re
11
 
12
  # تعريف LATEX_DELIMS
13
  LATEX_DELIMS = [
 
28
  HF_TOKEN = os.getenv("HF_TOKEN")
29
  API_ENDPOINT = os.getenv("API_ENDPOINT", "https://api-inference.huggingface.co/v1")
30
  MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b:cerebras")
31
+ SECONDARY_MODEL_NAME = os.getenv("SECONDARY_MODEL_NAME", "MGZON/mgzon-flan-t5-base")
32
  if not HF_TOKEN:
33
  logger.error("HF_TOKEN is not set in environment variables.")
34
  raise ValueError("HF_TOKEN is required for Inference API.")
 
38
  QUEUE_SIZE = int(os.getenv("QUEUE_SIZE", 80))
39
  CONCURRENCY_LIMIT = int(os.getenv("CONCURRENCY_LIMIT", 20))
40
 
41
+ # كلمات مفتاحية لتحديد إذا كان السؤال متعلق بـ MGZon
42
+ MGZON_KEYWORDS = [
43
+ "mgzon", "mgzon products", "mgzon services", "mgzon data", "mgzon platform",
44
+ "mgzon features", "mgzon mission", "mgzon technology", "mgzon solutions"
45
+ ]
46
+
47
+ # دالة لاختيار النموذج تلقائيًا
48
+ def select_model(query: str) -> str:
49
+ """Selects the appropriate model based on the query content."""
50
+ query_lower = query.lower()
51
+ for keyword in MGZON_KEYWORDS:
52
+ if keyword in query_lower:
53
+ logger.info(f"Selected {SECONDARY_MODEL_NAME} for MGZon-related query: {query}")
54
+ return SECONDARY_MODEL_NAME
55
+ logger.info(f"Selected {MODEL_NAME} for general query: {query}")
56
+ return MODEL_NAME
57
+
58
+ # دالة بحث ويب محسنة
59
+ def web_search(query: str) -> str:
60
+ try:
61
+ google_api_key = os.getenv("GOOGLE_API_KEY")
62
+ google_cse_id = os.getenv("GOOGLE_CSE_ID")
63
+ if not google_api_key or not google_cse_id:
64
+ return "Web search requires GOOGLE_API_KEY and GOOGLE_CSE_ID to be set."
65
+
66
+ url = f"https://www.googleapis.com/customsearch/v1?key={google_api_key}&cx={google_cse_id}&q={query}"
67
+ response = requests.get(url)
68
+ response.raise_for_status()
69
+ results = response.json().get("items", [])
70
+ if not results:
71
+ return "No web results found."
72
+
73
+ # جمع النتايج
74
+ search_results = []
75
+ for i, item in enumerate(results[:3]): # نأخذ أول 3 نتايج
76
+ title = item.get("title", "")
77
+ snippet = item.get("snippet", "")
78
+ link = item.get("link", "")
79
+ # محاولة استخراج محتوى الصفحة
80
+ try:
81
+ page_response = requests.get(link, timeout=5)
82
+ page_response.raise_for_status()
83
+ soup = BeautifulSoup(page_response.text, "html.parser")
84
+ # استخراج النصوص من الصفحة (فقط الفقرات)
85
+ paragraphs = soup.find_all("p")
86
+ page_content = " ".join([p.get_text() for p in paragraphs][:500]) # نأخذ أول 500 حرف
87
+ except Exception as e:
88
+ logger.warning(f"Failed to fetch page content for {link}: {e}")
89
+ page_content = snippet
90
+ search_results.append(f"Result {i+1}:\nTitle: {title}\nLink: {link}\nContent: {page_content}\n")
91
+
92
+ return "\n".join(search_results)
93
+ except Exception as e:
94
+ logger.exception("Web search failed")
95
+ return f"Web search error: {e}"
96
+
97
+ # دالة request_generation (محدثة لدعم المهام المتعددة)
98
  def request_generation(
99
  api_key: str,
100
  api_base: str,
 
102
  system_prompt: str,
103
  model_name: str,
104
  chat_history: Optional[List[dict]] = None,
105
+ temperature: float = 0.9,
106
+ max_new_tokens: int = 2048,
107
  reasoning_effort: str = "off",
108
  tools: Optional[List[dict]] = None,
109
  tool_choice: Optional[str] = None,
110
+ deep_search: bool = False,
111
  ) -> Generator[str, None, None]:
112
  """Streams Responses API events. Emits:
113
  - "analysis" sentinel once, then raw reasoning deltas
 
115
  If no visible deltas, emits a tool-call fallback message."""
116
  client = OpenAI(api_key=api_key, base_url=api_base)
117
 
118
+ # تحديد نوع المهمة بناءً على السؤال
119
+ task_type = "general"
120
+ if "code" in message.lower() or "programming" in message.lower() or any(ext in message.lower() for ext in ["python", "javascript", "react", "django", "flask"]):
121
+ task_type = "code"
122
+ enhanced_system_prompt = f"{system_prompt}\nYou are an expert programmer. Provide accurate, well-commented code with examples and explanations. Support frameworks like React, Django, Flask, and others as needed."
123
+ elif any(keyword in message.lower() for keyword in ["analyze", "analysis", "تحليل"]):
124
+ task_type = "analysis"
125
+ enhanced_system_prompt = f"{system_prompt}\nProvide detailed analysis with step-by-step reasoning, examples, and data-driven insights."
126
+ elif any(keyword in message.lower() for keyword in ["review", "مراجعة"]):
127
+ task_type = "review"
128
+ enhanced_system_prompt = f"{system_prompt}\nReview the provided content thoroughly, identify issues, and suggest improvements with detailed explanations."
129
+ elif any(keyword in message.lower() for keyword in ["publish", "نشر"]):
130
+ task_type = "publish"
131
+ enhanced_system_prompt = f"{system_prompt}\nPrepare content for publishing, ensuring clarity, professionalism, and adherence to best practices."
132
+ else:
133
+ enhanced_system_prompt = f"{system_prompt}\nPlease provide detailed and comprehensive responses, including explanations, examples, and relevant details where applicable."
134
+
135
+ logger.info(f"Task type detected: {task_type}")
136
+
137
  # تنظيف الـ messages من metadata
138
+ input_messages: List[dict] = [{"role": "system", "content": enhanced_system_prompt}]
139
  if chat_history:
140
  for msg in chat_history:
141
  clean_msg = {"role": msg.get("role"), "content": msg.get("content")}
142
  if clean_msg["content"]:
143
  input_messages.append(clean_msg)
144
+
145
+ # إذا كان DeepSearch مفعّل أو السؤال عام، أضف نتائج البحث
146
+ if deep_search or model_name == MODEL_NAME:
147
+ search_result = web_search(message)
148
+ input_messages.append({"role": "user", "content": f"User query: {message}\nWeb search context: {search_result}"})
149
+ else:
150
+ input_messages.append({"role": "user", "content": message})
151
+
152
+ # إعداد tools و tool_choice (فقط لـ GPT-based models)
153
+ tools = tools if tools and "gpt-oss" in model_name else []
154
+ tool_choice = tool_choice if tool_choice in ["auto", "none", "any", "required"] and "gpt-oss" in model_name else "none"
155
 
156
  try:
157
  stream = client.chat.completions.create(
 
193
  buffer = ""
194
  continue
195
 
196
+ if chunk.choices[0].delta.tool_calls and "gpt-oss" in model_name:
197
  tool_call = chunk.choices[0].delta.tool_calls[0]
198
  name = getattr(tool_call, "function", {}).get("name", None)
199
  args = getattr(tool_call, "function", {}).get("arguments", None)
 
253
  yield "Please enter a prompt."
254
  return
255
 
256
+ # اختيار النموذج تلقائيًا
257
+ model_name = select_model(message)
258
+
259
  # Flatten gradio history وتنظيف metadata
260
  chat_history = []
261
  for h in history:
 
268
  if u: chat_history.append({"role": "user", "content": u})
269
  if a: chat_history.append({"role": "assistant", "content": a})
270
 
271
+ # إعداد الأدوات
272
  tools = [
273
  {
274
  "type": "function",
275
  "function": {
276
  "name": "web_search_preview",
277
+ "description": "Perform a web search to gather additional context",
278
  "parameters": {
279
  "type": "object",
280
  "properties": {"query": {"type": "string", "description": "Search query"}},
281
  "required": ["query"],
282
  },
283
  },
284
+ },
285
+ {
286
+ "type": "function",
287
+ "function": {
288
+ "name": "code_generation",
289
+ "description": "Generate or modify code for various frameworks (React, Django, Flask, etc.)",
290
+ "parameters": {
291
+ "type": "object",
292
+ "properties": {
293
+ "code": {"type": "string", "description": "Existing code to modify or empty for new code"},
294
+ "framework": {"type": "string", "description": "Framework (e.g., React, Django, Flask)"},
295
+ "task": {"type": "string", "description": "Task description (e.g., create a component, fix a bug)"},
296
+ },
297
+ "required": ["task"],
298
+ },
299
+ },
300
  }
301
+ ] if "gpt-oss" in model_name else []
302
+ tool_choice = "auto" if "gpt-oss" in model_name else "none"
303
 
304
  in_analysis = False
305
  in_visible = False
 
325
  api_base=API_ENDPOINT,
326
  message=message,
327
  system_prompt=system_prompt,
328
+ model_name=model_name,
329
  chat_history=chat_history,
330
  temperature=temperature,
331
  max_new_tokens=max_new_tokens,
332
  tools=tools,
333
  tool_choice=tool_choice,
334
+ deep_search=enable_browsing or model_name == MODEL_NAME,
335
  )
336
 
337
  for chunk in stream:
 
381
  fn=generate,
382
  type="messages",
383
  chatbot=gr.Chatbot(
384
+ label="MGZon Chatbot",
385
  type="messages",
386
  height=600,
387
  latex_delimiters=LATEX_DELIMS,
388
  ),
389
  additional_inputs_accordion=gr.Accordion("⚙️ Settings", open=True),
390
  additional_inputs=[
391
+ gr.Textbox(label="System prompt", value="You are a helpful assistant capable of code generation, analysis, review, and more.", lines=2),
392
+ gr.Slider(label="Temperature", minimum=0.0, maximum=1.0, step=0.1, value=0.9),
393
  gr.Radio(label="Reasoning Effort", choices=["low", "medium", "high"], value="medium"),
394
+ gr.Checkbox(label="Enable DeepSearch (web browsing)", value=True),
395
+ gr.Slider(label="Max New Tokens", minimum=50, maximum=2048, step=50, value=2048),
396
  ],
397
  stop_btn="Stop",
398
  examples=[
399
  ["Explain the difference between supervised and unsupervised learning."],
400
+ ["Generate a React component for a login form."],
401
+ ["Review this Python code: print('Hello World')"],
402
+ ["Analyze the performance of a Django REST API."],
403
+ ["Tell me about MGZon products and services."],
404
+ ["Create a Flask route for user authentication."],
405
+ ["What are the latest trends in AI?"],
406
+ ["Provide guidelines for publishing a technical blog post."],
407
  ],
408
+ title="MGZon Chatbot",
409
+ description="A versatile chatbot powered by GPT-OSS-120B and MGZon-Flan-T5-Base (auto-selected based on query). Supports code generation, analysis, review, web search, and MGZon-specific queries. Licensed under Apache 2.0. ***DISCLAIMER:*** Analysis may contain internal thoughts not suitable for final response.",
410
  theme="gradio/soft",
411
  css=css,
412
  )
 
415
  from fastapi import FastAPI
416
  from gradio import mount_gradio_app
417
 
418
+ app = FastAPI(title="MGZon Chatbot API")
419
  app = mount_gradio_app(app, chatbot_ui, path="/")
420
 
421
  # تشغيل الخادم