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:
Kevin
2026-03-26 12:13:36 +08:00
parent 49b089354c
commit a3f61fcc0f
94 changed files with 3332 additions and 672 deletions

View File

@@ -34,9 +34,9 @@ class RedisService:
)
await self._client.ping()
logger.info("Redis 连接成功")
logger.debug("Redis 连接 URL: %s", self.redis_url)
logger.debug("Redis 连接 URL: {}", self.redis_url)
except Exception as e:
logger.error("Redis 连接失败: %s", e)
logger.error("Redis 连接失败: {}", e)
raise
return self._client
@@ -60,7 +60,7 @@ class RedisService:
return json.loads(data)
return []
except Exception as e:
logger.error("获取对话历史失败: %s", e)
logger.error("获取对话历史失败: {}", e)
return []
async def set_conversation_history(
@@ -75,7 +75,7 @@ class RedisService:
)
return True
except Exception as e:
logger.error("写入对话历史失败: %s", e)
logger.error("写入对话历史失败: {}", e)
return False
async def add_message(
@@ -112,7 +112,7 @@ class RedisService:
)
return True
except Exception as e:
logger.error("添加消息失败: %s", e)
logger.error("添加消息失败: {}", e)
return False
async def append_tts_audio_url_to_last_ai_message(
@@ -138,7 +138,7 @@ class RedisService:
break
else:
logger.warning(
"append_tts_audio_url: no ai message in history conversation_id=%s",
"append_tts_audio_url: no ai message in history conversation_id={}",
conversation_id,
)
return False
@@ -147,7 +147,7 @@ class RedisService:
)
return True
except Exception as e:
logger.error("append_tts_audio_url 失败: %s", e)
logger.error("append_tts_audio_url 失败: {}", e)
return False
async def clear_conversation_history(self, conversation_id: str) -> bool:
@@ -157,7 +157,7 @@ class RedisService:
await client.delete(key)
return True
except Exception as e:
logger.error("清除对话历史失败: %s", e)
logger.error("清除对话历史失败: {}", e)
return False
async def delete_keys_matching_pattern(self, pattern: str) -> int:
@@ -176,7 +176,7 @@ class RedisService:
deleted += int(await client.delete(*batch))
return deleted
except Exception as e:
logger.error("按 pattern 删除 Redis key 失败: %s", e)
logger.error("按 pattern 删除 Redis key 失败: {}", e)
return 0
async def extend_session_ttl(self, conversation_id: str) -> bool:
@@ -186,7 +186,7 @@ class RedisService:
await client.expire(key, self.session_ttl)
return True
except Exception as e:
logger.error("延长会话TTL失败: %s", e)
logger.error("延长会话TTL失败: {}", e)
return False
async def set_cache(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
@@ -203,7 +203,7 @@ class RedisService:
await client.set(key, data)
return True
except Exception as e:
logger.error("设置缓存失败: %s", e)
logger.error("设置缓存失败: {}", e)
return False
async def get_cache(self, key: str) -> Optional[Any]:
@@ -217,7 +217,7 @@ class RedisService:
return data
return None
except Exception as e:
logger.error("获取缓存失败: %s", e)
logger.error("获取缓存失败: {}", e)
return None
async def delete_cache(self, key: str) -> bool:
@@ -226,7 +226,7 @@ class RedisService:
await client.delete(key)
return True
except Exception as e:
logger.error("删除缓存失败: %s", e)
logger.error("删除缓存失败: {}", e)
return False
def is_available(self) -> bool: