Files
kefu/deploy/review-voice-20260918/integrate_visual_voice.py
T
2026-09-21 10:34:06 +08:00

81 lines
4.3 KiB
Python

from pathlib import Path
import shutil
helper = ''' def _wait_for_database_voice(self, fp, *, visible_voice=False):
"""Yield this task while local ASR works; unrelated conversations continue."""
from voice_messages import voice_batch_status
state = self._pending_reply_state(fp)
context = getattr(self, "_last_database_read", None)
bound = isinstance(context, dict) and context.get("fp_hex") == bytes(fp or b"").hex()
voice = voice_batch_status(context) if bound else {"status": "none"}
if visible_voice and voice["status"] == "none":
voice = {"status": "pending", "key": "visible-voice:" + bytes(fp or b"").hex(),
"reason": "等待语音对应的本机消息库和音频文件"}
if voice["status"] in {"none", "ready"}:
if state:
state.pop("voice_wait_key", None)
state.pop("voice_wait_started_at", None)
return False
if state is None:
return True # No durable task identity: never guess or answer an unheard voice.
now = time.time()
if state.get("voice_wait_key") != voice.get("key"):
state.update(voice_wait_key=voice.get("key"), voice_wait_started_at=now)
waiting = voice["status"] == "pending" and now - float(state.get("voice_wait_started_at") or now) < 180
if waiting:
state["ready_at"] = now + 2
self._set_task_stage(fp, "voice_transcribing", detail=voice.get("reason") or "语音正在本机转文字")
else:
reason = voice.get("reason") if voice["status"] == "error" else "语音转文字等待超时,尚未取得可核验文字,请人工处理"
state.update(manual_required=True, manual_reason=reason, awaiting_review=False,
reply_text="", staged_reply_text="", chat_text=str((context or {}).get("text") or ""))
self._set_task_stage(fp, "error", detail="语音需要人工核对", error=reason)
self._register_assistant_review(fp)
self._persist_pending_replies()
return True
'''
for label, project in [('source', Path('C:/kefu/wechat_rpa')), ('production', Path('C:/wechat_rpa'))]:
path = project / 'wechat_bot.py'
backup = Path(__file__).parent / 'before-voice-integration' / label
backup.mkdir(parents=True, exist_ok=True)
shutil.copy2(path, backup / path.name)
text = path.read_text(encoding='utf-8')
needle = ' def _database_message_direction(self, fp: bytes, text: str):\n'
assert text.count(needle) == 1
text = text.replace(needle, helper + needle)
needle = ''' database_text = self._database_chat_text(fp)
if database_text:
chat_text = database_text
'''
assert text.count(needle) == 1
text = text.replace(needle, needle + ''' if self._wait_for_database_voice(fp):
return None
from voice_messages import voice_batch_status
database_voice_ready = bool(database_text and voice_batch_status(getattr(self, "_last_database_read", None))["status"] == "ready")
''')
needle = ''' first_untrusted_batch = bool(
first_record_batch and not first_explicit_customer_text
)
'''
assert text.count(needle) == 1
text = text.replace(needle, ''' first_untrusted_batch = bool(
first_record_batch and not first_explicit_customer_text and not database_voice_ready
)
if database_voice_ready:
# Exact database identity and successful ASR make voice text available to normal model/risk processing.
reliable_text_pending = True
force_media_check = False
''')
needle = ''' self.report_operation("AI 准备", 2, 3, "语音没有转写,生成安全追问", fp)
print(" [AI] 检测到未转写语音,使用不猜测内容的安全回复")
ai_reply = safe_media_reply(media_types)
'''
assert text.count(needle) == 1
text = text.replace(needle, ''' self._wait_for_database_voice(fp, visible_voice=True)
return None
''')
path.write_text(text, encoding='utf-8')
print('Visual voice waiting/model flow integrated with targeted edits in both variants.')