|
|
@@ -900,15 +900,16 @@ async def femininity_chat(request: RoleBasedChatRequest):
|
|
|
if group_context:
|
|
|
cache_group_context(group_id, group_context, ttl=120)
|
|
|
|
|
|
- # 构造多模态消息格式
|
|
|
+ # 构造多模态消息格式,同步更新群情绪状态(去重由 update_group_mood 内部处理)
|
|
|
if group_context:
|
|
|
for msg in group_context[-20:]: # 最近20条
|
|
|
- user_id = msg['user_id']
|
|
|
+ msg_user_id = msg['user_id']
|
|
|
content_parts = []
|
|
|
|
|
|
- # 添加文本内容
|
|
|
+ # 添加文本内容,并更新群情绪
|
|
|
if msg.get('content'):
|
|
|
- content_parts.append({"type": "input_text", "text": f"{user_id}: {msg['content']}"})
|
|
|
+ content_parts.append({"type": "input_text", "text": f"{msg_user_id}: {msg['content']}"})
|
|
|
+ update_group_mood(group_id, msg_user_id, msg['content'])
|
|
|
|
|
|
# 添加图片
|
|
|
for img_url in msg.get('images', []):
|
|
|
@@ -997,6 +998,24 @@ async def femininity_chat(request: RoleBasedChatRequest):
|
|
|
如果不需要回应,保持沉默(不输出任何内容)。
|
|
|
"""
|
|
|
|
|
|
+ # 【v3.0新增】注入用户长期记忆(已确认的事实背景)
|
|
|
+ mem = get_user_memory(request.user_id, group_id, "femininity")
|
|
|
+ if mem and mem.get("facts"):
|
|
|
+ fact_lines = [
|
|
|
+ f"- {f['key']}: {f['value']}"
|
|
|
+ for f in mem["facts"]
|
|
|
+ if isinstance(f, dict) and f.get("key") and f.get("value")
|
|
|
+ ]
|
|
|
+ if fact_lines:
|
|
|
+ system_prompt += (
|
|
|
+ "\n\n## 你对当前发言用户的已知背景\n"
|
|
|
+ + "\n".join(fact_lines)
|
|
|
+ + "\n参照这些背景给出更贴近她实际情况的回应,但不要生硬复述。"
|
|
|
+ )
|
|
|
+
|
|
|
+ # 【v3.0新增】注入群情绪状态
|
|
|
+ system_prompt += build_mood_block(group_id)
|
|
|
+
|
|
|
# 构造请求消息
|
|
|
system_msg = {"role": "system", "content": [{"type": "input_text", "text": system_prompt}]}
|
|
|
|
|
|
@@ -1015,10 +1034,37 @@ async def femininity_chat(request: RoleBasedChatRequest):
|
|
|
else:
|
|
|
api_messages = [system_msg, {"role": "user", "content": user_content}]
|
|
|
|
|
|
- # 配置工具:联网搜索 + 知识库
|
|
|
- tools = get_web_search_tools()
|
|
|
+ # 【v3.0新增】知识库预检:直接调用 Viking SDK 检索
|
|
|
+ # 有命中 → 将切片内容作为上下文注入,不挂 Ark 知识库工具
|
|
|
+ # 无命中 → 挂联网搜索工具
|
|
|
+ tools = []
|
|
|
if knowledge_id:
|
|
|
- tools += get_knowledge_search_tools(knowledge_id,request.app_name)
|
|
|
+ try:
|
|
|
+ kb_results = await search_knowledge(
|
|
|
+ resource_id=knowledge_id,
|
|
|
+ query=request.message,
|
|
|
+ limit=5,
|
|
|
+ )
|
|
|
+ except Exception as e:
|
|
|
+ print(f"知识库预检失败,降级到联网搜索: {e}")
|
|
|
+ kb_results = []
|
|
|
+ else:
|
|
|
+ kb_results = []
|
|
|
+
|
|
|
+ if kb_results:
|
|
|
+ # 提取切片内容,拼接成上下文段落
|
|
|
+ kb_texts = [r.content for r in kb_results if r.content]
|
|
|
+ if kb_texts:
|
|
|
+ kb_context_block = [{"type": "input_text", "text": "【知识库参考资料】\n" + "\n\n".join(kb_texts) + "\n\n请优先基于以上资料回答,资料中没有的内容不要编造。"}]
|
|
|
+ # 将知识库上下文插入到 user content 前面
|
|
|
+ if context_messages:
|
|
|
+ api_messages[-1]["content"] = kb_context_block + api_messages[-1]["content"]
|
|
|
+ else:
|
|
|
+ api_messages[-1]["content"] = kb_context_block + user_content
|
|
|
+ # 有知识库命中时不挂任何工具
|
|
|
+ else:
|
|
|
+ # 无命中,降级到联网搜索
|
|
|
+ tools = get_web_search_tools()
|
|
|
|
|
|
# 调用 AI 客户端
|
|
|
response = client.responses.create(
|
|
|
@@ -1058,6 +1104,17 @@ async def femininity_chat(request: RoleBasedChatRequest):
|
|
|
app_name=request.app_name,
|
|
|
)
|
|
|
|
|
|
+ # 【v3.0新增】异步抽取用户记忆(fire-and-forget,失败不影响主流程)
|
|
|
+ if result:
|
|
|
+ asyncio.create_task(_extract_memory(
|
|
|
+ user_id=request.user_id,
|
|
|
+ group_id=group_id,
|
|
|
+ ai_role="femininity",
|
|
|
+ trigger_msg=request.message,
|
|
|
+ ai_reply=result,
|
|
|
+ app_name=request.app_name,
|
|
|
+ ))
|
|
|
+
|
|
|
if not result:
|
|
|
save_chat_log(
|
|
|
user_id=request.user_id,
|