feat(api+app): 对话阶段化、回忆录流水线与客户端会话体验
- DB: segments 用户输入文本(Alembic 0002) - Chat: 阶段检测/阶段提示/回复限制,编排与访谈/画像 prompts 调整 - Memoir: 忠实度检查 agent,叙事与分类等链路更新 - Core: agent 日志、Alembic 启动、LangChain/日志/配置等 - Story: time_hints;Memory 检索与相关测试 - Expo: 助手头像、会话页与消息拆分、实时会话与文案/i18n - Docs/scripts/tests: 迁移脚本、LLM JSON/记忆检索文档、新增单测
This commit is contained in:
@@ -29,7 +29,7 @@ class TencentASRProvider:
|
||||
self._client = asr_client.AsrClient(cred, "", client_profile)
|
||||
return self._client
|
||||
except Exception as e:
|
||||
logger.error("Tencent ASR client init failed: %s", e)
|
||||
logger.error("Tencent ASR client init failed: {}", e)
|
||||
return None
|
||||
|
||||
def ensure_ready(self) -> bool:
|
||||
@@ -53,5 +53,5 @@ class TencentASRProvider:
|
||||
resp = client.SentenceRecognition(req)
|
||||
return (resp.Result or "").strip()
|
||||
except Exception as e:
|
||||
logger.error("Tencent ASR transcribe failed: %s", e)
|
||||
logger.error("Tencent ASR transcribe failed: {}", e)
|
||||
return ""
|
||||
|
||||
@@ -63,7 +63,7 @@ class WhisperASRProvider:
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error("Failed to load Whisper model: %s", e)
|
||||
logger.error("Failed to load Whisper model: {}", e)
|
||||
return False
|
||||
|
||||
def ensure_ready(self) -> bool:
|
||||
@@ -89,7 +89,7 @@ class WhisperASRProvider:
|
||||
)
|
||||
return "".join(seg.text for seg in segments).strip()
|
||||
except Exception as e:
|
||||
logger.error("Whisper transcribe failed: %s", e)
|
||||
logger.error("Whisper transcribe failed: {}", e)
|
||||
return ""
|
||||
finally:
|
||||
if tmp_path and os.path.exists(tmp_path):
|
||||
|
||||
@@ -163,7 +163,7 @@ class LiblibImageProvider:
|
||||
f"Liblib returned undocumented status 7 for {job['job_id']}"
|
||||
)
|
||||
logger.debug(
|
||||
"Liblib poll attempt %d/%d, status=%s, job=%s",
|
||||
"Liblib poll attempt {}/{}, status={}, job={}",
|
||||
attempt + 1,
|
||||
max_attempts,
|
||||
status,
|
||||
@@ -218,6 +218,7 @@ def _redact_sensitive_query_values(value):
|
||||
|
||||
|
||||
def _install_http_log_redaction() -> None:
|
||||
"""对 httpx/httpcore 的标准库 Logger 挂 Filter(非 loguru get_logger)。"""
|
||||
for logger_name in (
|
||||
"httpx",
|
||||
"httpcore",
|
||||
@@ -225,7 +226,7 @@ def _install_http_log_redaction() -> None:
|
||||
"httpcore.http11",
|
||||
"httpcore.proxy",
|
||||
):
|
||||
target_logger = get_logger(logger_name)
|
||||
target_logger = logging.getLogger(logger_name)
|
||||
if getattr(target_logger, "_liblib_auth_redaction_installed", False):
|
||||
continue
|
||||
target_logger.addFilter(_LiblibAuthRedactionFilter())
|
||||
|
||||
@@ -9,7 +9,8 @@ class DeepSeekLLMProvider:
|
||||
"""LangChain-based LLM adapter for DeepSeek and OpenAI-compatible APIs.
|
||||
|
||||
`langchain_llm` 供 Agent / 任务同步调用;若需 JSON object 模式,请用
|
||||
`app.core.langchain_llm.bind_json_object_mode` 绑定,勿使用已废弃的
|
||||
`app.core.langchain_llm.bind_json_object_mode` 或 `invoke_json_object` /
|
||||
`ainvoke_json_object`(见 `api/docs/llm-json-mode.md`),勿使用已废弃的
|
||||
`bind(model_kwargs={"response_format": ...})`。
|
||||
"""
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class TencentSmsSender:
|
||||
if "TemplateParamSetNotMatchApprovedTemplate" in error_code:
|
||||
continue
|
||||
logger.error(
|
||||
"SMS send failed: %s - %s",
|
||||
"SMS send failed: {} - {}",
|
||||
error_code,
|
||||
status.Message if status else "",
|
||||
)
|
||||
@@ -73,10 +73,10 @@ class TencentSmsSender:
|
||||
except TencentCloudSDKException as e:
|
||||
if "TemplateParamSetNotMatchApprovedTemplate" in str(e):
|
||||
continue
|
||||
logger.error("Tencent SMS SDK error: %s", e)
|
||||
logger.error("Tencent SMS SDK error: {}", e)
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error("SMS send exception: %s", e)
|
||||
logger.error("SMS send exception: {}", e)
|
||||
return False
|
||||
|
||||
logger.error("All SMS template param configs failed")
|
||||
|
||||
@@ -51,4 +51,4 @@ class TencentCosStorage:
|
||||
try:
|
||||
self._client.delete_object(Bucket=self._bucket, Key=key)
|
||||
except (CosClientError, CosServiceError) as e:
|
||||
logger.warning("COS delete failed: key=%s, error=%s", key, e)
|
||||
logger.warning("COS delete failed: key={}, error={}", key, e)
|
||||
|
||||
@@ -90,7 +90,7 @@ class TencentTTSProvider:
|
||||
self._client = tts_client.TtsClient(cred, "", client_profile)
|
||||
return self._client
|
||||
except Exception as e:
|
||||
logger.error("Tencent TTS client init failed: %s", e)
|
||||
logger.error("Tencent TTS client init failed: {}", e)
|
||||
return None
|
||||
|
||||
def _synthesize_sync(self, text: str, voice_type: int) -> bytes:
|
||||
@@ -116,10 +116,10 @@ class TencentTTSProvider:
|
||||
return b""
|
||||
return base64.b64decode(resp.Audio)
|
||||
except TencentCloudSDKException as e:
|
||||
logger.error("Tencent TTS SDK error: %s", e)
|
||||
logger.error("Tencent TTS SDK error: {}", e)
|
||||
return b""
|
||||
except Exception as e:
|
||||
logger.error("Tencent TTS synthesize failed: %s", e)
|
||||
logger.error("Tencent TTS synthesize failed: {}", e)
|
||||
return b""
|
||||
|
||||
async def synthesize(self, text: str, voice: str = "alloy") -> bytes:
|
||||
|
||||
Reference in New Issue
Block a user