Spaces:
Running
Running
Update clare_core.py
Browse files- clare_core.py +81 -0
clare_core.py
CHANGED
|
@@ -176,6 +176,40 @@ def detect_language(message: str, preference: str) -> str:
|
|
| 176 |
if re.search(r"[\u4e00-\u9fff]", message):
|
| 177 |
return "中文"
|
| 178 |
return "English"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
|
| 181 |
# ---------- Session 状态展示 ----------
|
|
@@ -317,6 +351,53 @@ def find_similar_past_question(
|
|
| 317 |
|
| 318 |
return None
|
| 319 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
|
| 321 |
# ---------- 构建 messages ----------
|
| 322 |
def build_messages(
|
|
|
|
| 176 |
if re.search(r"[\u4e00-\u9fff]", message):
|
| 177 |
return "中文"
|
| 178 |
return "English"
|
| 179 |
+
|
| 180 |
+
def get_empty_input_prompt(lang: str) -> str:
|
| 181 |
+
"""
|
| 182 |
+
空输入时的友好提示,根据语言返回中/英文。
|
| 183 |
+
"""
|
| 184 |
+
if lang == "中文":
|
| 185 |
+
return "请先输入一个问题或想法,再按回车发送,我才能帮到你哦。"
|
| 186 |
+
# 默认英文
|
| 187 |
+
return "Please type a question or some text before sending, then hit Enter."
|
| 188 |
+
|
| 189 |
+
def build_error_message(
|
| 190 |
+
e: Exception,
|
| 191 |
+
lang: str,
|
| 192 |
+
op: str = "chat",
|
| 193 |
+
) -> str:
|
| 194 |
+
"""
|
| 195 |
+
针对不同操作类型(普通对话 / quiz / summary)和语言,生成友好的错误提示。
|
| 196 |
+
不把原始异常直接暴露给学生,只在后台打印。
|
| 197 |
+
"""
|
| 198 |
+
if lang == "中文":
|
| 199 |
+
prefix = {
|
| 200 |
+
"chat": "抱歉,刚刚在和模型对话时出现了一点问题。",
|
| 201 |
+
"quiz": "抱歉,刚刚在生成测验题目时出现了一点问题。",
|
| 202 |
+
"summary": "抱歉,刚刚在生成总结时出现了一点问题。",
|
| 203 |
+
}.get(op, "抱歉,刚刚出现了一点问题。")
|
| 204 |
+
return prefix + " 请稍后再试一次,或者换个问法试试。"
|
| 205 |
+
|
| 206 |
+
# 默认英文
|
| 207 |
+
prefix_en = {
|
| 208 |
+
"chat": "Sorry, I ran into a problem while talking to the model.",
|
| 209 |
+
"quiz": "Sorry, there was a problem while generating the quiz.",
|
| 210 |
+
"summary": "Sorry, there was a problem while generating the summary.",
|
| 211 |
+
}.get(op, "Sorry, something went wrong just now.")
|
| 212 |
+
return prefix_en + " Please try again in a moment or rephrase your request."
|
| 213 |
|
| 214 |
|
| 215 |
# ---------- Session 状态展示 ----------
|
|
|
|
| 351 |
|
| 352 |
return None
|
| 353 |
|
| 354 |
+
from config import client, DEFAULT_MODEL, EMBEDDING_MODEL # 确认已导入 DEFAULT_MODEL
|
| 355 |
+
|
| 356 |
+
def safe_chat_completion(
|
| 357 |
+
model_name: str,
|
| 358 |
+
messages: List[Dict[str, str]],
|
| 359 |
+
lang: str,
|
| 360 |
+
op: str = "chat",
|
| 361 |
+
temperature: float = 0.5,
|
| 362 |
+
) -> str:
|
| 363 |
+
"""
|
| 364 |
+
统一安全调用 OpenAI Chat Completion:
|
| 365 |
+
- 最多尝试 2 次
|
| 366 |
+
- 每次请求 timeout = 20 秒
|
| 367 |
+
- 第一次用学生选择的模型;出错后,如果不是 DEFAULT_MODEL,则自动回退到 DEFAULT_MODEL 再试一次
|
| 368 |
+
- 所有异常都会打印到后台 log,但对学生只返回友好的中/英文错误文案
|
| 369 |
+
"""
|
| 370 |
+
preferred_model = model_name or DEFAULT_MODEL
|
| 371 |
+
last_error: Optional[Exception] = None
|
| 372 |
+
|
| 373 |
+
for attempt in range(2):
|
| 374 |
+
# 第一次用学生指定模型,第二次(如果需要)切到默认模型
|
| 375 |
+
if attempt == 0:
|
| 376 |
+
current_model = preferred_model
|
| 377 |
+
else:
|
| 378 |
+
current_model = DEFAULT_MODEL
|
| 379 |
+
|
| 380 |
+
try:
|
| 381 |
+
resp = client.chat.completions.create(
|
| 382 |
+
model=current_model,
|
| 383 |
+
messages=messages,
|
| 384 |
+
temperature=temperature,
|
| 385 |
+
timeout=20, # 20 秒超时
|
| 386 |
+
)
|
| 387 |
+
return resp.choices[0].message.content
|
| 388 |
+
except Exception as e:
|
| 389 |
+
print(
|
| 390 |
+
f"[safe_chat_completion][{op}] attempt {attempt+1} "
|
| 391 |
+
f"failed with model={current_model}: {repr(e)}"
|
| 392 |
+
)
|
| 393 |
+
last_error = e
|
| 394 |
+
|
| 395 |
+
# 如果已经用的是默认模型,或者已经是第二次尝试,就跳出循环
|
| 396 |
+
if current_model == DEFAULT_MODEL or attempt == 1:
|
| 397 |
+
break
|
| 398 |
+
|
| 399 |
+
# 两次都失败,返回友好的错误文案
|
| 400 |
+
return build_error_message(last_error or Exception("unknown error"), lang, op)
|
| 401 |
|
| 402 |
# ---------- 构建 messages ----------
|
| 403 |
def build_messages(
|