Spaces:
Sleeping
Sleeping
File size: 5,893 Bytes
8bb704c 5fcfe49 8bb704c 021749e 8bb704c 9f628a1 8bb704c 651a393 8bb704c 021749e 51a8ded 8bb704c 651a393 8bb704c 651a393 49ea7ef 651a393 a1e849a 021749e 8bb704c 9f628a1 5fcfe49 4609451 9f628a1 021749e 8bb704c 9f628a1 5fcfe49 a6cd490 5fcfe49 9f628a1 a6cd490 5fcfe49 a6cd490 8bb704c 9f628a1 8bb704c 51a8ded 0184e81 49ea7ef 8bb704c 5fcfe49 a6cd490 5fcfe49 8bb704c 4609451 8bb704c 51a8ded a1e849a 8bb704c a1e849a 651a393 8bb704c c78b0c8 8bb704c 7ce643e 8bb704c 7ce643e 8bb704c 7ce643e 8bb704c c78b0c8 51a8ded c78b0c8 8bb704c c78b0c8 8bb704c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
import os
import gradio as gr
import backoff
from cerebras.cloud.sdk import APIConnectionError, APIStatusError, Cerebras, RateLimitError
from dotenv import load_dotenv
from opencc import OpenCC
from utils.utils import get_pinyin
from verification.verifier import verify_idiom_exists
# ======================
# Config
# ======================
load_dotenv()
MODEL = "gpt-oss-120b"
USE_MOCK = False # ✅ Toggle between mock and real API
# simplified to traditional Chinese character converter
char_converter = OpenCC('s2t')
# Set default to Traditional characters due to user base
IS_TRADITIONAL = True
# ======================
# Instantiate client (if not mocking)
# ======================
CLIENT = None
if not USE_MOCK:
CLIENT = Cerebras(api_key=os.environ.get("CEREBRAS_API_KEY"))
def format_explanation(pinyin_text: str, translation: str, meaning: str) -> str:
return f"""
<div style="line-height: 1.4; margin: 0;">
<p style="margin: 0;">
{pinyin_text}
</p>
<div style="margin-top: 8px;">
<i>{translation}</i><br>
{meaning}
</div>
</div>
"""
# ======================
# Mock function for UI testing
# ======================
def find_idiom_mock():
idiom = "对症下药"
pinyin_text = "duì zhèng xià yào"
translation = "To prescribe the right medicine; to take the right approach to a problem."
meaning = "add a meaning for the mock"
explanation = format_explanation(pinyin_text, translation, meaning)
idiom_output = f"{idiom}<br>"
return idiom_output, explanation
# ======================
# Real API function
# ======================
# Global cache for repeated situations
EXAMPLE_CACHE = {}
@backoff.on_exception(backoff.expo, RateLimitError)
def find_idiom(situation: str, max_attempts: int = 3):
"""
Find a verified Chinese idiom for a given situation.
Uses verify_idiom_exists() to confirm idiom validity.
"""
if situation in EXAMPLE_CACHE:
return EXAMPLE_CACHE[situation]
prompt = f"""You are a wise assistant. Given a situation, respond with exactly:
1. A Chinese idiom (includes 成語、俗語、諺語),
written in simplified Chinese characters,
that conveys the idea of the given situation.
2. Its literal English translation
3. Explain idiom in English. Keep explanation to 2-3 concise sentences.
Format:
Idiom
Literal translation
Explanation
Situation: {situation}
Answer:"""
response = CLIENT.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
)
generated_text = response.choices[0].message.content.strip()
lines = [line.strip() for line in generated_text.split("\n") if line.strip()]
llm_idiom = lines[0] if lines else generated_text
trad_idiom = char_converter.convert(llm_idiom) if char_converter else None
# 2️⃣ Verify idiom using CC-CEDICT + Wiktionary
if verify_idiom_exists(llm_idiom):
pinyin_text = get_pinyin(llm_idiom)
if len(lines) >= 3:
translation = lines[1]
meaning = " ".join(lines[2:])
else:
translation = ""
meaning = " ".join(lines[1:])
explanation = format_explanation(pinyin_text, translation, meaning)
EXAMPLE_CACHE[situation] = (llm_idiom, explanation)
idiom_output = f"{llm_idiom}<br>{trad_idiom}"
return idiom_output, explanation
# Fallback if no verified idiom found
fallback_idiom = "未找到成语"
fallback_explanation = "No verified idiom found for this situation."
return fallback_idiom, fallback_explanation
# ======================
# UI Wrapper
# ======================
def update_ui(situation):
if USE_MOCK:
idiom, explanation = find_idiom_mock()
else:
try:
idiom, explanation = find_idiom(situation)
except RateLimitError:
idiom = ""
explanation = "<div class='error-message'>Too many requests. Please try again later.</div>"
idiom, explanation = find_idiom(situation)
idiom_output = char_converter.convert(idiom.split("<br>")[0]) if IS_TRADITIONAL else idiom
return (
f"<div class='idiom-output'>{idiom_output}</div>",
f"<div class='explanation-output' style='margin-top: 1px;'>{explanation}</div>",
)
# ======================
# Launch app
# ======================
def launch_app():
with gr.Blocks(css="style.css") as demo:
gr.Markdown("# 🎋 Chinese Idiom Finder")
with gr.Row():
with gr.Column():
situation = gr.Textbox(
label="Enter a situation",
lines=2,
placeholder="e.g., When facing a big challenge",
)
generate_btn = gr.Button("✨ Find Idiom")
# ✅ Example situations
gr.Examples(
examples=[
["When facing a big challenge"],
["When someone helps you in a time of need"],
["When you need to stay calm under pressure"],
["When teamwork is important to succeed"],
["When rushing leads to mistakes"],
],
inputs=situation,
)
with gr.Column():
idiom_output = gr.HTML(label="Idiom")
explanation_output = gr.HTML(label="Explanation")
# pylint: disable=no-member
generate_btn.click(
fn=update_ui,
inputs=[situation],
outputs=[idiom_output, explanation_output],
)
demo.launch()
if __name__ == "__main__":
launch_app()
|