NANInithin commited on
Commit ·
855ae1e
1
Parent(s): d3f0718
feat: debugging asr and minicpm
Browse files- app.py +2 -1
- app/services/minicpm.py +22 -6
app.py
CHANGED
|
@@ -1275,7 +1275,8 @@ with gr.Blocks(title="CityQuest · AI") as demo:
|
|
| 1275 |
with gr.Row():
|
| 1276 |
with gr.Column():
|
| 1277 |
gr.HTML("<div class='section-label'>Voice journal</div>")
|
| 1278 |
-
d_audio = gr.Audio(sources=["microphone"
|
|
|
|
| 1279 |
d_lang = gr.Dropdown(
|
| 1280 |
["en", "fr", "de", "it", "es", "pt", "el", "nl", "pl",
|
| 1281 |
"zh", "ja", "ko", "vi", "ar"],
|
|
|
|
| 1275 |
with gr.Row():
|
| 1276 |
with gr.Column():
|
| 1277 |
gr.HTML("<div class='section-label'>Voice journal</div>")
|
| 1278 |
+
d_audio = gr.Audio(sources=["microphone", "upload"], type="filepath",
|
| 1279 |
+
format="wav", label="Record or upload audio")
|
| 1280 |
d_lang = gr.Dropdown(
|
| 1281 |
["en", "fr", "de", "it", "es", "pt", "el", "nl", "pl",
|
| 1282 |
"zh", "ja", "ko", "vi", "ar"],
|
app/services/minicpm.py
CHANGED
|
@@ -123,7 +123,22 @@ def warm() -> bool:
|
|
| 123 |
return _get_llm() is not None
|
| 124 |
|
| 125 |
|
| 126 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
"""In-game MiniCPM helper: answer a player's question (clue / explain a
|
| 128 |
task / tell me about this place). Returns plain text, or ``None`` if the
|
| 129 |
model is unavailable so the caller can show a graceful fallback."""
|
|
@@ -134,7 +149,7 @@ def ask(question: str, context: str = "", max_tokens: int = 320) -> Optional[str
|
|
| 134 |
"You are CityQuest's friendly in-game guide for a real-world city "
|
| 135 |
"adventure game. Give a short, warm, practical answer (2-4 sentences). "
|
| 136 |
"Help with clues, understanding tasks, and local places. Never reveal "
|
| 137 |
-
"winners or scores. Plain text only."
|
| 138 |
)
|
| 139 |
user = question if not context else f"Context:\n{context}\n\nQuestion: {question}"
|
| 140 |
|
|
@@ -145,8 +160,9 @@ def ask(question: str, context: str = "", max_tokens: int = 320) -> Optional[str
|
|
| 145 |
{"role": "user", "content": user}],
|
| 146 |
max_tokens=max_tokens, temperature=0.6, top_p=0.9,
|
| 147 |
)
|
| 148 |
-
|
| 149 |
-
|
|
|
|
| 150 |
if text:
|
| 151 |
return text
|
| 152 |
except Exception as e:
|
|
@@ -164,8 +180,8 @@ def ask(question: str, context: str = "", max_tokens: int = 320) -> Optional[str
|
|
| 164 |
prompt, max_tokens=max_tokens, temperature=0.6, top_p=0.9,
|
| 165 |
stop=["<|im_end|>", "<|im_start|>", "</s>"],
|
| 166 |
)
|
| 167 |
-
text = (out["choices"][0]["text"] or "").strip()
|
| 168 |
-
print(f"[minicpm] ask(raw)
|
| 169 |
return text or None
|
| 170 |
except Exception as e:
|
| 171 |
print(f"[minicpm] ask(raw) failed: {type(e).__name__}: {e}")
|
|
|
|
| 123 |
return _get_llm() is not None
|
| 124 |
|
| 125 |
|
| 126 |
+
def _strip_think(text: str) -> str:
|
| 127 |
+
"""Remove MiniCPM5 reasoning blocks.
|
| 128 |
+
|
| 129 |
+
MiniCPM5 is a reasoning model that emits ``<think>…</think>`` before its
|
| 130 |
+
answer. Those tags render invisibly in Markdown (they look like HTML), so
|
| 131 |
+
we drop the whole block and keep only the final answer. Also handles an
|
| 132 |
+
unclosed ``<think>`` (answer was truncated by max_tokens).
|
| 133 |
+
"""
|
| 134 |
+
import re
|
| 135 |
+
text = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL | re.IGNORECASE)
|
| 136 |
+
# If a think block was opened but never closed (truncation), drop the rest.
|
| 137 |
+
text = re.sub(r"<think>.*$", "", text, flags=re.DOTALL | re.IGNORECASE)
|
| 138 |
+
return text.strip()
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def ask(question: str, context: str = "", max_tokens: int = 640) -> Optional[str]:
|
| 142 |
"""In-game MiniCPM helper: answer a player's question (clue / explain a
|
| 143 |
task / tell me about this place). Returns plain text, or ``None`` if the
|
| 144 |
model is unavailable so the caller can show a graceful fallback."""
|
|
|
|
| 149 |
"You are CityQuest's friendly in-game guide for a real-world city "
|
| 150 |
"adventure game. Give a short, warm, practical answer (2-4 sentences). "
|
| 151 |
"Help with clues, understanding tasks, and local places. Never reveal "
|
| 152 |
+
"winners or scores. Plain text only. Do not show your reasoning."
|
| 153 |
)
|
| 154 |
user = question if not context else f"Context:\n{context}\n\nQuestion: {question}"
|
| 155 |
|
|
|
|
| 160 |
{"role": "user", "content": user}],
|
| 161 |
max_tokens=max_tokens, temperature=0.6, top_p=0.9,
|
| 162 |
)
|
| 163 |
+
raw = (result["choices"][0]["message"]["content"] or "").strip()
|
| 164 |
+
text = _strip_think(raw)
|
| 165 |
+
print(f"[minicpm] ask(chat) raw_len={len(raw)} answer_len={len(text)} preview={text[:80]!r}")
|
| 166 |
if text:
|
| 167 |
return text
|
| 168 |
except Exception as e:
|
|
|
|
| 180 |
prompt, max_tokens=max_tokens, temperature=0.6, top_p=0.9,
|
| 181 |
stop=["<|im_end|>", "<|im_start|>", "</s>"],
|
| 182 |
)
|
| 183 |
+
text = _strip_think((out["choices"][0]["text"] or "").strip())
|
| 184 |
+
print(f"[minicpm] ask(raw) answer_len={len(text)} preview={text[:80]!r}")
|
| 185 |
return text or None
|
| 186 |
except Exception as e:
|
| 187 |
print(f"[minicpm] ask(raw) failed: {type(e).__name__}: {e}")
|