Spaces:
Running
Running
import os | |
import re | |
import cohere | |
import gradio as gr | |
from typing import Iterator, List, Tuple | |
# Configuration Constants | |
DEFAULT_SYSTEM_PROMPT = """ | |
أنت مترجم ثنائي اللغة متخصص في الترجمة بين العربية والإنجليزية. هدفك هو تقديم ترجمات دقيقة، ملائمة للسياق، ومتسقة من الناحية الأسلوبية، مع الالتزام بالإرشادات التالية: | |
أسلوب الكتابة: | |
1. الدقة النحوية: احرص دائمًا على أن تكون الترجمة صحيحة نحويًا. | |
2. الملاءمة السياقية: قم بتكييف الترجمة مع السياق والجمهور المستهدف: | |
استخدم جملًا موجزة وواضحة في المحتوى الطبي والقانوني. | |
اعتمد لغة جذابة وخيالية في المواد التسويقية. | |
حافظ على الرسمية والبلاغة في المحتوى القانوني. | |
3. البنية السليمة: احترم تراكيب الجمل العربية وتجنب النسخ المباشر لقواعد لغة المصدر. فضل استخدام "الجملة الفعلية" إلا إذا كانت "الجملة الاسمية" أكثر ملاءمة (مثلًا في العناوين أو التنويهات). | |
الخيارات الأسلوبية: | |
استخدم التشكيل فقط عند الضرورة لتوضيح المعنى. | |
تعامل مع الأسماء والأحرف المختصرة حسب السياق: | |
قم بتعريب الأسماء وأسماء الأدوية إلا إذا وُجدت لها مرادفات عربية. | |
ترجم أسماء البرامج والإدارات والهيئات عندما يكون ذلك مفيدًا. | |
استخدم الأرقام العربية وتأكد من التعامل الصحيح مع الوحدات والعناوين والمراجع. | |
علامات الترقيم: | |
طبق قواعد الترقيم العربية لضمان وضوح النص. | |
استخدم الفاصلة العربية (،) والفاصلة المنقوطة (؛) حسب الأعراف. | |
تجنب الإفراط في استخدام علامات الاقتباس واحرص على وضع النقطتين (:) بشكل منطقي. | |
الأخطاء الشائعة التي يجب تجنبها: | |
تجنب ترجمة "is" بـ "يُعتبر" إلا إذا كان ذلك مناسبًا للسياق. | |
استخدم حروف الجر والعطف بشكل صحيح لضمان تدفق الجمل بسلاسة. | |
قلل من التكرار واستخدم الضمائر حيثما أمكن. | |
تجنب الإفراط في استخدام تراكيب مثل "(قام + الفعل)" و"الخاص بـ." | |
المصطلحات المحددة: | |
في الترجمات القانونية، حافظ على النبرة الرسمية وتأكد من دقة المصطلحات. | |
في الترجمات الطبية، بسّط المصطلحات التقنية للجمهور العام مع الاحتفاظ بالتعقيد عند مخاطبة المتخصصين. | |
في الترجمات التسويقية، ركّز على الإبداع بدلًا من الترجمة الحرفية، مع الحفاظ على الرسالة الأساسية. | |
إرشادات التنسيق: | |
التزم بمعايير الطباعة العربية بشكل متسق. | |
حافظ على تنسيق البيانات المهمة (مثل التواريخ، والقياسات، والاستشهادات القانونية). | |
عند الشك: | |
قدم الأولوية للوضوح، والتناسق، والملاءمة مع احتياجات الجمهور المستهدف. قم دائمًا بموازنة التعليمات الخاصة بالمشروع مع هذه الإرشادات، مع إعطاء الأولوية لمتطلبات العميل عند وجود أي تعارض. | |
""" # Full prompt maintained as original | |
TITLE = "<h1><center>Mawared T Assistant</center></h1>" | |
PLACEHOLDER = "Ask me anything! I'll think through it step by step." | |
CSS = """ | |
duplicate-button { | |
margin: auto !important; | |
color: white !important; | |
background: black !important; | |
border-radius: 100vh !important; | |
} | |
h3 { | |
text-align: center; | |
} | |
.message-wrap { | |
overflow-x: auto; | |
} | |
.message-wrap p { | |
margin-bottom: 1em; | |
} | |
.message-wrap pre { | |
background-color: #f6f8fa; | |
border-radius: 3px; | |
padding: 16px; | |
overflow-x: auto; | |
} | |
.message-wrap code { | |
background-color: rgba(175,184,193,0.2); | |
border-radius: 3px; | |
padding: 0.2em 0.4em; | |
font-family: monospace; | |
} | |
.custom-tag { | |
color: #0066cc; | |
font-weight: bold; | |
} | |
.chat-area { | |
height: 500px !important; | |
overflow-y: auto !important; | |
} | |
""" | |
# Precompile regex patterns for better performance | |
TAG_PATTERNS = [ | |
(re.compile(r'<Thinking>'), '\n<Thinking>\n'), | |
(re.compile(r'</Thinking>'), '\n</Thinking>\n'), | |
(re.compile(r'<Critique>'), '\n<Critique>\n'), | |
(re.compile(r'</Critique>'), '\n</Critique>\n'), | |
(re.compile(r'<Revising>'), '\n<Revising>\n'), | |
(re.compile(r'</Revising>'), '\n</Revising>\n'), | |
(re.compile(r'<Final>'), '\n<Final>\n'), | |
(re.compile(r'</Final>'), '\n</Final>\n') | |
] | |
def format_text(text: str) -> str: | |
"""Format text with proper spacing and tag highlighting""" | |
formatted = text | |
for pattern, replacement in TAG_PATTERNS: | |
formatted = pattern.sub(replacement, formatted) | |
return '\n'.join(line for line in formatted.split('\n') if line.strip()) | |
def format_chat_history(history: List[List[str]]) -> str: | |
"""Format chat history for display""" | |
return "\n\n".join( | |
f"User: {user_msg}\nAssistant: {assistant_msg}" | |
for user_msg, assistant_msg in history if user_msg | |
) | |
def convert_history_to_cohere_format(history: List[List[str]]) -> List[dict]: | |
"""Convert chat history to Cohere's format with proper roles""" | |
cohere_history = [] | |
for user_msg, assistant_msg in history: | |
if user_msg: | |
cohere_history.append({"role": "USER", "message": user_msg}) | |
if assistant_msg: | |
cohere_history.append({"role": "CHATBOT", "message": assistant_msg}) | |
return cohere_history | |
def chat_response( | |
message: str, | |
history: List[List[str]], | |
chat_display: str, | |
system_prompt: str, | |
temperature: float = 0.2, | |
max_new_tokens: int = 8192, | |
top_p: float = 0.8, | |
top_k: int = 40, | |
penalty: float = 1.2, | |
api_key: str = os.getenv("COHERE_API_KEY") | |
) -> Iterator[Tuple[List[List[str]], str]]: | |
"""Generate chat responses using Cohere API with error handling""" | |
if not api_key: | |
error_message = "Error: COHERE_API_KEY environment variable not set." | |
history.append([message, error_message]) | |
yield history, format_chat_history(history) | |
return | |
co = cohere.Client(api_key=api_key) | |
chat_history = convert_history_to_cohere_format(history) | |
buffer = "" | |
history.append([message, ""]) | |
try: | |
stream = co.chat_stream( | |
model='c4ai-aya-expanse-32b', | |
message=message, | |
temperature=temperature, | |
max_tokens=max_new_tokens, | |
p=top_p, | |
k=top_k, | |
frequency_penalty=penalty, | |
chat_history=chat_history, | |
prompt_truncation='AUTO', | |
preamble=system_prompt | |
) | |
for event in stream: | |
if event.event_type == "text-generation": | |
buffer += event.text | |
history[-1][1] = format_text(buffer) | |
yield history, format_chat_history(history) | |
except Exception as e: | |
error_message = f"Error: {str(e)}" | |
history[-1][1] = error_message | |
yield history, format_chat_history(history) | |
def main(): | |
"""Main function to set up and launch the Gradio interface""" | |
with gr.Blocks(css=CSS, theme="soft") as demo: | |
gr.HTML(TITLE) | |
gr.DuplicateButton( | |
value="Duplicate Space for private use", | |
elem_classes="duplicate-button" | |
) | |
with gr.Row(): | |
with gr.Column(): | |
chat_history = gr.State([]) | |
chat_display = gr.TextArea( | |
value="", | |
label="Chat History", | |
interactive=False, | |
elem_classes=["chat-area"], | |
) | |
message = gr.TextArea( | |
placeholder=PLACEHOLDER, | |
label="Your message", | |
lines=3, | |
elem_id="message_input" | |
) | |
with gr.Row(): | |
submit = gr.Button("Send", elem_id="submit_btn") | |
clear = gr.Button("Clear") | |
with gr.Accordion("⚙️ Advanced Settings", open=False): | |
system_prompt = gr.TextArea( | |
value=DEFAULT_SYSTEM_PROMPT, | |
label="System Prompt", | |
lines=5, | |
) | |
temperature = gr.Slider( | |
minimum=0, | |
maximum=1, | |
step=0.1, | |
value=0.2, | |
label="Temperature", | |
) | |
max_tokens = gr.Slider( | |
minimum=128, | |
maximum=32000, | |
step=128, | |
value=8192, | |
label="Max Tokens", | |
) | |
top_p = gr.Slider( | |
minimum=0.1, | |
maximum=1.0, | |
step=0.1, | |
value=0.8, | |
label="Top-p", | |
) | |
top_k = gr.Slider( | |
minimum=1, | |
maximum=100, | |
step=1, | |
value=40, | |
label="Top-k", | |
) | |
penalty = gr.Slider( | |
minimum=1.0, | |
maximum=2.0, | |
step=0.1, | |
value=1.2, | |
label="Repetition Penalty", | |
) | |
# Event handlers | |
submit.click( | |
chat_response, | |
inputs=[message, chat_history, chat_display, system_prompt, | |
temperature, max_tokens, top_p, top_k, penalty], | |
outputs=[chat_history, chat_display], | |
show_progress=True, | |
).then(lambda: "", outputs=message) | |
message.submit( | |
chat_response, | |
inputs=[message, chat_history, chat_display, system_prompt, | |
temperature, max_tokens, top_p, top_k, penalty], | |
outputs=[chat_history, chat_display], | |
show_progress=True, | |
).then(lambda: "", outputs=message) | |
clear.click( | |
lambda: ([], ""), | |
outputs=[chat_history, chat_display], | |
show_progress=True, | |
) | |
# Add JavaScript for Enter key handling | |
if __name__ == "__main__": | |
demo = main() | |
demo.launch() |