Spaces:
Running
Running
Make a bilingual version: Egglish and Chinese
Browse files
app.py
CHANGED
|
@@ -48,16 +48,16 @@ def validate_json(output: str) -> tuple:
|
|
| 48 |
try:
|
| 49 |
json_match = re.search(r'\{[\s\S]*\}', output)
|
| 50 |
if not json_match:
|
| 51 |
-
return False, None, "
|
| 52 |
|
| 53 |
json_str = json_match.group(0)
|
| 54 |
json_str = re.sub(r',\s*\}', '}', json_str)
|
| 55 |
parsed = json.loads(json_str)
|
| 56 |
-
return True, parsed, "
|
| 57 |
except json.JSONDecodeError:
|
| 58 |
-
return False, None, "
|
| 59 |
except Exception:
|
| 60 |
-
return False, None, "
|
| 61 |
|
| 62 |
def extract_reservation_info(text: str):
|
| 63 |
"""Extract reservation information from text"""
|
|
@@ -65,7 +65,7 @@ def extract_reservation_info(text: str):
|
|
| 65 |
model, tokenizer = load_model()
|
| 66 |
|
| 67 |
if model is None or tokenizer is None:
|
| 68 |
-
return {"error": "
|
| 69 |
|
| 70 |
try:
|
| 71 |
# Create chat template
|
|
@@ -107,65 +107,157 @@ def extract_reservation_info(text: str):
|
|
| 107 |
return {"error": message}, assistant_output
|
| 108 |
|
| 109 |
except Exception as e:
|
| 110 |
-
return {"error": f"
|
| 111 |
|
| 112 |
# Create Gradio interface
|
| 113 |
def create_interface():
|
| 114 |
"""Create the Gradio interface"""
|
| 115 |
-
|
| 116 |
"你好,我想訂明天晚上7點的位子,四位成人,電話是0912-345-678",
|
| 117 |
"週六下午三點,兩位,電話0987654321",
|
| 118 |
"預約下週三中午12點半,5人用餐,聯絡電話0912345678",
|
| 119 |
"我要訂位,3個人,今天下午6點"
|
| 120 |
]
|
| 121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
with gr.Blocks(
|
| 123 |
-
title="
|
| 124 |
theme=gr.themes.Soft()
|
| 125 |
) as demo:
|
| 126 |
-
|
| 127 |
-
gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
|
| 129 |
with gr.Row():
|
| 130 |
with gr.Column():
|
| 131 |
input_text = gr.Textbox(
|
| 132 |
-
label="
|
| 133 |
-
placeholder="
|
| 134 |
lines=3
|
| 135 |
)
|
| 136 |
-
submit_btn = gr.Button("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
|
|
|
| 138 |
gr.Examples(
|
| 139 |
-
examples=
|
| 140 |
inputs=input_text,
|
| 141 |
-
label="
|
| 142 |
)
|
| 143 |
|
| 144 |
with gr.Column():
|
| 145 |
-
json_output = gr.JSON(label="
|
| 146 |
raw_output = gr.Textbox(
|
| 147 |
-
label="
|
| 148 |
interactive=False,
|
| 149 |
lines=3
|
| 150 |
)
|
| 151 |
|
| 152 |
# Info panel
|
| 153 |
-
with gr.Accordion("ℹ️
|
| 154 |
-
gr.Markdown("""
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
- 模型會輸出JSON格式的結果
|
| 164 |
-
""")
|
| 165 |
|
| 166 |
# Footer
|
| 167 |
-
gr.Markdown("
|
| 168 |
-
gr.Markdown("由 [Together AI](https://together.ai) 提供技術支持 | 模型: Luigi/gemma-3-270m-it-dinercall-ner")
|
| 169 |
|
| 170 |
# Connect the function to the button
|
| 171 |
submit_btn.click(
|
|
@@ -173,6 +265,26 @@ def create_interface():
|
|
| 173 |
inputs=input_text,
|
| 174 |
outputs=[json_output, raw_output]
|
| 175 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
return demo
|
| 178 |
|
|
@@ -186,4 +298,4 @@ if __name__ == "__main__":
|
|
| 186 |
server_name="0.0.0.0",
|
| 187 |
server_port=7860,
|
| 188 |
share=False
|
| 189 |
-
)
|
|
|
|
| 48 |
try:
|
| 49 |
json_match = re.search(r'\{[\s\S]*\}', output)
|
| 50 |
if not json_match:
|
| 51 |
+
return False, None, "No JSON found"
|
| 52 |
|
| 53 |
json_str = json_match.group(0)
|
| 54 |
json_str = re.sub(r',\s*\}', '}', json_str)
|
| 55 |
parsed = json.loads(json_str)
|
| 56 |
+
return True, parsed, "Valid JSON"
|
| 57 |
except json.JSONDecodeError:
|
| 58 |
+
return False, None, "Invalid JSON format"
|
| 59 |
except Exception:
|
| 60 |
+
return False, None, "Error parsing JSON"
|
| 61 |
|
| 62 |
def extract_reservation_info(text: str):
|
| 63 |
"""Extract reservation information from text"""
|
|
|
|
| 65 |
model, tokenizer = load_model()
|
| 66 |
|
| 67 |
if model is None or tokenizer is None:
|
| 68 |
+
return {"error": "Model not loaded, please refresh the page"}, ""
|
| 69 |
|
| 70 |
try:
|
| 71 |
# Create chat template
|
|
|
|
| 107 |
return {"error": message}, assistant_output
|
| 108 |
|
| 109 |
except Exception as e:
|
| 110 |
+
return {"error": f"Processing error: {str(e)}"}, ""
|
| 111 |
|
| 112 |
# Create Gradio interface
|
| 113 |
def create_interface():
|
| 114 |
"""Create the Gradio interface"""
|
| 115 |
+
chinese_examples = [
|
| 116 |
"你好,我想訂明天晚上7點的位子,四位成人,電話是0912-345-678",
|
| 117 |
"週六下午三點,兩位,電話0987654321",
|
| 118 |
"預約下週三中午12點半,5人用餐,聯絡電話0912345678",
|
| 119 |
"我要訂位,3個人,今天下午6點"
|
| 120 |
]
|
| 121 |
|
| 122 |
+
english_examples = [
|
| 123 |
+
"Hello, I'd like to reserve a table for 4 people tomorrow at 7 PM, phone number is 0912-345-678",
|
| 124 |
+
"Saturday 3 PM, 2 people, phone 0987654321",
|
| 125 |
+
"Reservation for next Wednesday at 12:30 PM, 5 people, contact number 0912345678",
|
| 126 |
+
"I want to make a reservation, 3 people, today at 6 PM"
|
| 127 |
+
]
|
| 128 |
+
|
| 129 |
+
# Language-specific text dictionaries
|
| 130 |
+
text_en = {
|
| 131 |
+
"title": "🍽️ Restaurant Reservation Info Extractor",
|
| 132 |
+
"description": "Use AI to automatically extract reservation information from messages",
|
| 133 |
+
"input_label": "Input reservation message",
|
| 134 |
+
"input_placeholder": "e.g., Hello, I'd like to reserve a table for 4 people tomorrow at 7 PM, phone number is 0912-345-678",
|
| 135 |
+
"button_text": "Extract Information",
|
| 136 |
+
"json_label": "Extracted Result",
|
| 137 |
+
"raw_label": "Raw Output",
|
| 138 |
+
"instructions_title": "ℹ️ Instructions",
|
| 139 |
+
"instructions": """**Supported information:**
|
| 140 |
+
- 👥 Number of people (num_people)
|
| 141 |
+
- 📅 Reservation date/time (reservation_date)
|
| 142 |
+
- 📞 Phone number (phone_num)
|
| 143 |
+
|
| 144 |
+
**Notes:**
|
| 145 |
+
- First-time model loading may take a few minutes
|
| 146 |
+
- If you encounter errors, try refreshing the page
|
| 147 |
+
- The model outputs results in JSON format""",
|
| 148 |
+
"footer": "Powered by [Together AI](https://together.ai) | Model: Luigi/gemma-3-270m-it-dinercall-ner",
|
| 149 |
+
"examples_title": "Examples",
|
| 150 |
+
"chinese_examples": "Chinese Examples",
|
| 151 |
+
"english_examples": "English Examples"
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
text_zh = {
|
| 155 |
+
"title": "🍽️ 餐廳訂位資訊提取器",
|
| 156 |
+
"description": "使用AI從中文訊息中自動提取訂位資訊",
|
| 157 |
+
"input_label": "輸入訂位訊息",
|
| 158 |
+
"input_placeholder": "例如: 你好,我想訂明天晚上7點的位子,四位成人,電話是0912-345-678",
|
| 159 |
+
"button_text": "提取資訊",
|
| 160 |
+
"json_label": "提取結果",
|
| 161 |
+
"raw_label": "原始輸出",
|
| 162 |
+
"instructions_title": "ℹ️ 使用說明",
|
| 163 |
+
"instructions": """**支援提取的資訊:**
|
| 164 |
+
- 👥 人數 (num_people)
|
| 165 |
+
- 📅 預訂日期/時間 (reservation_date)
|
| 166 |
+
- 📞 電話號碼 (phone_num)
|
| 167 |
+
|
| 168 |
+
**注意事項:**
|
| 169 |
+
- 首次加載模型可能需要幾分鐘時間
|
| 170 |
+
- 如果遇到錯誤,請嘗試刷新頁面
|
| 171 |
+
- 模型會輸出JSON格式的結果""",
|
| 172 |
+
"footer": "由 [Together AI](https://together.ai) 提供技術支持 | 模型: Luigi/gemma-3-270m-it-dinercall-ner",
|
| 173 |
+
"examples_title": "示例",
|
| 174 |
+
"chinese_examples": "中文示例",
|
| 175 |
+
"english_examples": "英文示例"
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
def update_interface(language):
|
| 179 |
+
"""Update interface based on selected language"""
|
| 180 |
+
texts = text_en if language == "English" else text_zh
|
| 181 |
+
return [
|
| 182 |
+
gr.Markdown.update(value=f"# {texts['title']}"),
|
| 183 |
+
gr.Markdown.update(value=texts['description']),
|
| 184 |
+
gr.Textbox.update(
|
| 185 |
+
label=texts['input_label'],
|
| 186 |
+
placeholder=texts['input_placeholder']
|
| 187 |
+
),
|
| 188 |
+
gr.Button.update(value=texts['button_text']),
|
| 189 |
+
gr.JSON.update(label=texts['json_label']),
|
| 190 |
+
gr.Textbox.update(label=texts['raw_label']),
|
| 191 |
+
gr.Accordion.update(label=texts['instructions_title']),
|
| 192 |
+
gr.Markdown.update(value=texts['instructions']),
|
| 193 |
+
gr.Markdown.update(value=texts['footer']),
|
| 194 |
+
gr.Markdown.update(value=f"### {texts['examples_title']}"),
|
| 195 |
+
gr.Markdown.update(value=f"### {texts['chinese_examples']}"),
|
| 196 |
+
gr.Markdown.update(value=f"### {texts['english_examples']}")
|
| 197 |
+
]
|
| 198 |
+
|
| 199 |
with gr.Blocks(
|
| 200 |
+
title="Restaurant Reservation Info Extractor",
|
| 201 |
theme=gr.themes.Soft()
|
| 202 |
) as demo:
|
| 203 |
+
# Language selector
|
| 204 |
+
language = gr.Radio(
|
| 205 |
+
choices=["English", "中文"],
|
| 206 |
+
value="English",
|
| 207 |
+
label="Language / 语言",
|
| 208 |
+
interactive=True
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
# Main interface components
|
| 212 |
+
title_md = gr.Markdown("# Restaurant Reservation Info Extractor")
|
| 213 |
+
description_md = gr.Markdown("Use AI to automatically extract reservation information from messages")
|
| 214 |
|
| 215 |
with gr.Row():
|
| 216 |
with gr.Column():
|
| 217 |
input_text = gr.Textbox(
|
| 218 |
+
label="Input reservation message",
|
| 219 |
+
placeholder="e.g., Hello, I'd like to reserve a table for 4 people tomorrow at 7 PM, phone number is 0912-345-678",
|
| 220 |
lines=3
|
| 221 |
)
|
| 222 |
+
submit_btn = gr.Button("Extract Information", variant="primary")
|
| 223 |
+
|
| 224 |
+
examples_title_md = gr.Markdown("### Examples")
|
| 225 |
+
chinese_examples_title_md = gr.Markdown("### Chinese Examples")
|
| 226 |
+
gr.Examples(
|
| 227 |
+
examples=chinese_examples,
|
| 228 |
+
inputs=input_text,
|
| 229 |
+
label="Chinese Examples"
|
| 230 |
+
)
|
| 231 |
|
| 232 |
+
english_examples_title_md = gr.Markdown("### English Examples")
|
| 233 |
gr.Examples(
|
| 234 |
+
examples=english_examples,
|
| 235 |
inputs=input_text,
|
| 236 |
+
label="English Examples"
|
| 237 |
)
|
| 238 |
|
| 239 |
with gr.Column():
|
| 240 |
+
json_output = gr.JSON(label="Extracted Result")
|
| 241 |
raw_output = gr.Textbox(
|
| 242 |
+
label="Raw Output",
|
| 243 |
interactive=False,
|
| 244 |
lines=3
|
| 245 |
)
|
| 246 |
|
| 247 |
# Info panel
|
| 248 |
+
with gr.Accordion("ℹ️ Instructions", open=False) as instructions_accordion:
|
| 249 |
+
instructions_md = gr.Markdown("""**Supported information:**
|
| 250 |
+
- 👥 Number of people (num_people)
|
| 251 |
+
- 📅 Reservation date/time (reservation_date)
|
| 252 |
+
- 📞 Phone number (phone_num)
|
| 253 |
+
|
| 254 |
+
**Notes:**
|
| 255 |
+
- First-time model loading may take a few minutes
|
| 256 |
+
- If you encounter errors, try refreshing the page
|
| 257 |
+
- The model outputs results in JSON format""")
|
|
|
|
|
|
|
| 258 |
|
| 259 |
# Footer
|
| 260 |
+
footer_md = gr.Markdown("Powered by [Together AI](https://together.ai) | Model: Luigi/gemma-3-270m-it-dinercall-ner")
|
|
|
|
| 261 |
|
| 262 |
# Connect the function to the button
|
| 263 |
submit_btn.click(
|
|
|
|
| 265 |
inputs=input_text,
|
| 266 |
outputs=[json_output, raw_output]
|
| 267 |
)
|
| 268 |
+
|
| 269 |
+
# Connect language selector to update interface
|
| 270 |
+
language.change(
|
| 271 |
+
fn=update_interface,
|
| 272 |
+
inputs=language,
|
| 273 |
+
outputs=[
|
| 274 |
+
title_md,
|
| 275 |
+
description_md,
|
| 276 |
+
input_text,
|
| 277 |
+
submit_btn,
|
| 278 |
+
json_output,
|
| 279 |
+
raw_output,
|
| 280 |
+
instructions_accordion,
|
| 281 |
+
instructions_md,
|
| 282 |
+
footer_md,
|
| 283 |
+
examples_title_md,
|
| 284 |
+
chinese_examples_title_md,
|
| 285 |
+
english_examples_title_md
|
| 286 |
+
]
|
| 287 |
+
)
|
| 288 |
|
| 289 |
return demo
|
| 290 |
|
|
|
|
| 298 |
server_name="0.0.0.0",
|
| 299 |
server_port=7860,
|
| 300 |
share=False
|
| 301 |
+
)
|