Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,46 +1,10 @@
|
|
1 |
import gradio as gr
|
2 |
from huggingface_hub import InferenceClient
|
3 |
-
import os
|
4 |
|
5 |
-
#
|
6 |
-
HF_TOKEN = os.getenv("HF_TOKEN")
|
7 |
-
|
8 |
-
# Initialize client with proper error handling
|
9 |
-
def get_client():
|
10 |
-
if HF_TOKEN:
|
11 |
-
try:
|
12 |
-
# Try with the preferred model first
|
13 |
-
return InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=HF_TOKEN)
|
14 |
-
except Exception as e:
|
15 |
-
print(f"Failed to initialize zephyr model: {e}")
|
16 |
-
# Fallback to mistral with token
|
17 |
-
try:
|
18 |
-
return InferenceClient("mistralai/Mistral-7B-Instruct-v0.1", token=HF_TOKEN)
|
19 |
-
except Exception as e2:
|
20 |
-
print(f"Failed to initialize mistral model: {e2}")
|
21 |
-
return None
|
22 |
-
else:
|
23 |
-
print("No HF_TOKEN found. Please set your Hugging Face token.")
|
24 |
-
return None
|
25 |
-
|
26 |
-
client = get_client()
|
27 |
-
|
28 |
-
# Dynamic prompt builder based on CEFR level
|
29 |
-
def level_to_prompt(level):
|
30 |
-
return {
|
31 |
-
"A1": "You are a friendly French tutor. Speak mostly in English, use simple French, and explain everything.",
|
32 |
-
"A2": "You are a patient French tutor. Use short French phrases and explain them in English.",
|
33 |
-
"B1": "You are a helpful French tutor. Speak mostly in French but clarify in English when needed.",
|
34 |
-
"B2": "You are a French tutor. Speak primarily in French with rare English support.",
|
35 |
-
"C1": "You are a native French tutor. Speak entirely in French, clearly and professionally.",
|
36 |
-
"C2": "You are a native French professor. Speak in rich, complex French. Avoid English."
|
37 |
-
}.get(level, "You are a helpful French tutor.")
|
38 |
-
|
39 |
-
# Custom background CSS
|
40 |
css = """
|
41 |
-
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP&family=Playfair+Display&display=swap');
|
42 |
body {
|
43 |
-
background-image: url('https://cdn-uploads.huggingface.co/production/uploads/67351c643fe51cb1aa28f2e5/
|
44 |
background-size: cover;
|
45 |
background-position: center;
|
46 |
background-repeat: no-repeat;
|
@@ -52,142 +16,111 @@ body {
|
|
52 |
min-height: 100vh;
|
53 |
padding-top: 2rem;
|
54 |
padding-bottom: 2rem;
|
55 |
-
}
|
56 |
#chat-panel {
|
57 |
background-color: rgba(255, 255, 255, 0.85);
|
58 |
padding: 2rem;
|
59 |
border-radius: 12px;
|
|
|
|
|
60 |
max-width: 700px;
|
61 |
height: 70vh;
|
62 |
-
margin: auto;
|
63 |
box-shadow: 0 0 12px rgba(0, 0, 0, 0.3);
|
64 |
overflow-y: auto;
|
65 |
}
|
|
|
66 |
.gradio-container .chatbot h1 {
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
}
|
75 |
"""
|
76 |
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
-
# Generate response
|
87 |
response = ""
|
88 |
-
try:
|
89 |
-
# Create a proper prompt format for instruction-following models
|
90 |
-
prompt = f"<|system|>\n{system_message}\n\n"
|
91 |
-
|
92 |
-
# Add conversation history
|
93 |
-
if history:
|
94 |
-
for turn in history:
|
95 |
-
if isinstance(turn, dict):
|
96 |
-
if turn.get("role") == "user":
|
97 |
-
prompt += f"<|user|>\n{turn['content']}\n\n"
|
98 |
-
elif turn.get("role") == "assistant":
|
99 |
-
prompt += f"<|assistant|>\n{turn['content']}\n\n"
|
100 |
-
else:
|
101 |
-
# Handle tuple format (user, assistant)
|
102 |
-
user_msg, bot_msg = turn
|
103 |
-
if user_msg:
|
104 |
-
prompt += f"<|user|>\n{user_msg}\n\n"
|
105 |
-
if bot_msg:
|
106 |
-
prompt += f"<|assistant|>\n{bot_msg}\n\n"
|
107 |
-
|
108 |
-
# Add current user message
|
109 |
-
prompt += f"<|user|>\n{message}\n\n<|assistant|>\n"
|
110 |
-
|
111 |
-
# Generate response with streaming
|
112 |
-
for token in client.text_generation(
|
113 |
-
prompt,
|
114 |
-
max_new_tokens=max_tokens,
|
115 |
-
stream=True,
|
116 |
-
temperature=temperature,
|
117 |
-
top_p=top_p,
|
118 |
-
do_sample=True,
|
119 |
-
return_full_text=False,
|
120 |
-
stop_sequences=["<|user|>", "<|system|>"] # Stop if model tries to continue conversation
|
121 |
-
):
|
122 |
-
if token: # Handle None tokens
|
123 |
-
# Clean up any unwanted tokens
|
124 |
-
token = token.replace("<|user|>", "").replace("<|system|>", "").replace("<|assistant|>", "")
|
125 |
-
if token.strip(): # Only add non-empty tokens
|
126 |
-
response += token
|
127 |
-
yield response
|
128 |
-
|
129 |
-
except Exception as e:
|
130 |
-
error_msg = str(e)
|
131 |
-
print(f"Error in chat completion: {e}")
|
132 |
-
|
133 |
-
if "401" in error_msg or "Unauthorized" in error_msg:
|
134 |
-
yield "🔑 Authentication Error: Please check your Hugging Face token. Make sure it's valid and has the correct permissions."
|
135 |
-
elif "429" in error_msg or "rate limit" in error_msg.lower():
|
136 |
-
yield "⏰ Rate limit exceeded. Please wait a moment before trying again."
|
137 |
-
elif "503" in error_msg or "Service Unavailable" in error_msg:
|
138 |
-
yield "🔧 The AI service is temporarily unavailable. Please try again later."
|
139 |
-
else:
|
140 |
-
yield f"❌ Désolé! There was an error: {error_msg}"
|
141 |
-
|
142 |
-
# UI layout
|
143 |
-
with gr.Blocks(css=css, title="French Tutor") as demo:
|
144 |
-
gr.Markdown("# 🇫🇷 French Tutor", elem_id="custom-title")
|
145 |
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
with gr.Column(elem_id="chat-panel"):
|
153 |
-
gr.
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
choices=["A1", "A2", "B1", "B2", "C1", "C2"],
|
158 |
-
value="A1",
|
159 |
-
label="Your French Level (CEFR)",
|
160 |
-
info="Choose your current French proficiency level"
|
161 |
)
|
162 |
max_tokens = gr.Slider(
|
163 |
-
1,
|
|
|
164 |
value=512,
|
165 |
step=1,
|
166 |
-
label="Response Length"
|
167 |
-
info="Maximum number of tokens in the response"
|
168 |
)
|
169 |
temperature = gr.Slider(
|
170 |
-
0.1,
|
|
|
171 |
value=0.7,
|
172 |
step=0.1,
|
173 |
-
label="Creativity"
|
174 |
-
info="Higher values make responses more creative"
|
175 |
)
|
176 |
top_p = gr.Slider(
|
177 |
-
0.1,
|
|
|
178 |
value=0.95,
|
179 |
step=0.05,
|
180 |
-
label="Dynamic Text"
|
181 |
-
info="Controls text diversity"
|
182 |
)
|
183 |
|
184 |
gr.ChatInterface(
|
185 |
-
|
186 |
-
additional_inputs=[
|
187 |
-
|
188 |
-
|
189 |
-
|
|
|
|
|
|
|
190 |
)
|
191 |
-
|
192 |
if __name__ == "__main__":
|
193 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
from huggingface_hub import InferenceClient
|
|
|
3 |
|
4 |
+
# Custom background CSS with semi-transparent panel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
css = """
|
|
|
6 |
body {
|
7 |
+
background-image: url('https://cdn-uploads.huggingface.co/production/uploads/67351c643fe51cb1aa28f2e5/vcVnxPZhCXRVL2fn3rG6B.jpeg');
|
8 |
background-size: cover;
|
9 |
background-position: center;
|
10 |
background-repeat: no-repeat;
|
|
|
16 |
min-height: 100vh;
|
17 |
padding-top: 2rem;
|
18 |
padding-bottom: 2rem;
|
19 |
+
}
|
20 |
#chat-panel {
|
21 |
background-color: rgba(255, 255, 255, 0.85);
|
22 |
padding: 2rem;
|
23 |
border-radius: 12px;
|
24 |
+
justify-content: center;
|
25 |
+
width: 100%;
|
26 |
max-width: 700px;
|
27 |
height: 70vh;
|
|
|
28 |
box-shadow: 0 0 12px rgba(0, 0, 0, 0.3);
|
29 |
overflow-y: auto;
|
30 |
}
|
31 |
+
/* Improved title styling */
|
32 |
.gradio-container .chatbot h1 {
|
33 |
+
color: var(--custom-title-color) !important;
|
34 |
+
font-family: 'Noto Sans', serif !important;
|
35 |
+
font-size: 5rem !important; /* Increased font size */
|
36 |
+
font-weight: bold !important;
|
37 |
+
text-align: center !important;
|
38 |
+
margin-bottom: 1.5rem !important;
|
39 |
+
width: 100%; /* Ensure full width for centering */
|
40 |
}
|
41 |
"""
|
42 |
|
43 |
+
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
|
44 |
+
|
45 |
+
def respond(
|
46 |
+
message,
|
47 |
+
history,
|
48 |
+
system_message,
|
49 |
+
max_tokens,
|
50 |
+
temperature,
|
51 |
+
top_p,
|
52 |
+
):
|
53 |
+
messages = [{"role": "system", "content": system_message}]
|
54 |
|
55 |
+
# Handle history based on its format (tuple format or messages format)
|
56 |
+
if history and isinstance(history[0], tuple):
|
57 |
+
# Old tuple format
|
58 |
+
for user_msg, assistant_msg in history:
|
59 |
+
if user_msg:
|
60 |
+
messages.append({"role": "user", "content": user_msg})
|
61 |
+
if assistant_msg:
|
62 |
+
messages.append({"role": "assistant", "content": assistant_msg})
|
63 |
+
else:
|
64 |
+
# New messages format
|
65 |
+
messages.extend(history)
|
66 |
+
|
67 |
+
messages.append({"role": "user", "content": message})
|
68 |
|
|
|
69 |
response = ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
for msg in client.chat_completion(
|
72 |
+
messages,
|
73 |
+
max_tokens=max_tokens,
|
74 |
+
stream=True,
|
75 |
+
temperature=temperature,
|
76 |
+
top_p=top_p,
|
77 |
+
):
|
78 |
+
token = msg.choices[0].delta.content
|
79 |
+
response += token
|
80 |
+
yield response
|
81 |
+
|
82 |
+
with gr.Blocks(css=css) as demo:
|
83 |
+
# Title Markdown block
|
84 |
+
gr.Markdown("French Instructor", elem_id="custom-title")
|
85 |
|
86 |
with gr.Column(elem_id="chat-panel"):
|
87 |
+
with gr.Accordion("Advanced Settings", open=False):
|
88 |
+
system_message = gr.Textbox(
|
89 |
+
value="You are a helpful French language tutor. You help users learn French vocabulary, grammar, and cultural contexts. When appropriate, include both the French writing and pronunciation. For beginners, focus on simple phrases and gradually increase difficulty based on user proficiency.",
|
90 |
+
label="System Message"
|
|
|
|
|
|
|
|
|
91 |
)
|
92 |
max_tokens = gr.Slider(
|
93 |
+
minimum=1,
|
94 |
+
maximum=2048,
|
95 |
value=512,
|
96 |
step=1,
|
97 |
+
label="Response Length"
|
|
|
98 |
)
|
99 |
temperature = gr.Slider(
|
100 |
+
minimum=0.1,
|
101 |
+
maximum=4.0,
|
102 |
value=0.7,
|
103 |
step=0.1,
|
104 |
+
label="Creativity"
|
|
|
105 |
)
|
106 |
top_p = gr.Slider(
|
107 |
+
minimum=0.1,
|
108 |
+
maximum=1.0,
|
109 |
value=0.95,
|
110 |
step=0.05,
|
111 |
+
label="Dynamic Text"
|
|
|
112 |
)
|
113 |
|
114 |
gr.ChatInterface(
|
115 |
+
respond,
|
116 |
+
additional_inputs=[
|
117 |
+
system_message,
|
118 |
+
max_tokens,
|
119 |
+
temperature,
|
120 |
+
top_p
|
121 |
+
],
|
122 |
+
type="messages" # Set to new message format
|
123 |
)
|
124 |
+
|
125 |
if __name__ == "__main__":
|
126 |
demo.launch()
|