fix(wechat-bot): ①对话时间统一北京时间 ②媒体内联发送(微信直看图片/视频) ③媒体生成计入Token驾驶舱 ④清空技能市场

This commit is contained in:
QihuAI Design committed 2026-07-15 23:37:30 +08:00
1 parent 7739f17594
commit da89a27bca
3 files changed
+166 -42

No files matched your search

+43 -6
View File
@@ -14,7 +14,9 @@ IM Bot 真实 LLM 调用。
"""
import asyncio
import json
import logging
import re as _re
from datetime import datetime, timezone, timedelta
from typing import Optional
from urllib.parse import urlparse as _urlparse
@@ -22,7 +24,9 @@ import httpx
from sqlalchemy.orm import Session
from ..capability_registry import resolve_auto_model
from ..models import AIModel, ModelProvider
from ..models import AIModel, ModelProvider, TokenUsageLog, gen_uuid
logger = logging.getLogger(__name__)
# 香港出网代理(实测对 AGNES 延迟更低,2026-07-15 用户实测),与 chat.py 同值。
@@ -65,7 +69,37 @@ def _run_async(coro):
return asyncio.run(coro)
def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im", user_id: str = None) -> str:
def _log_media_usage(db: Session, user_id: str, ai_model, media_type: str, prompt: str):
"""IM Bot 媒体生成记账:把图片/视频消耗写入 TokenUsageLog,供驾驶舱统计。
此前 IM Bot 路径完全不写 TokenUsageLog,导致微信生成的图片/视频在驾驶舱里“查无此项”。
媒体 API 不返回 token 用量,这里用与 chat.py _generate_media_task 一致的估算。
"""
if not user_id or not ai_model:
return
try:
base = 1200 if media_type == "video" else 400
est = base + (len(prompt or "") // 4)
db.add(TokenUsageLog(
id=gen_uuid(),
user_id=user_id,
model_id=ai_model.id,
model_name=ai_model.name,
prompt_tokens=est,
completion_tokens=0,
total_tokens=est,
created_at=datetime.now(timezone(timedelta(hours=8))).replace(tzinfo=None),
))
db.commit()
except Exception as e:
try:
db.rollback()
except Exception:
pass
logger.warning(f"[im_llm] 媒体 Token 记账失败(忽略): {e}")
def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im", user_id: str = None) -> "str | dict":
"""调用七虎AI 生成回复,供 IM Bot 复用。支持媒体意图路由与已安装技能自动发现。"""
try:
from app.api.chat import (
@@ -88,19 +122,22 @@ def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im
# 绝不直接把原始异常(如 "Server disconnected")甩给用户
result = "⚠️ 媒体生成暂时失败(连接或服务波动),请稍后重试。"
if result:
# IM 不渲染 HTML,把 <img>/<video> 还原为纯文本链接返回
# 媒体生成成功:返回结构化对象,交由 im_bot_user 在微信内联发送图片/视频
s = result.strip()
if s.startswith("<img") or s.startswith("<video"):
m = _re.search(r'src="([^"]+)"', s)
url = m.group(1) if m else ""
label = "图片" if s.startswith("<img") else "视频"
return f"已为你生成{label}:{url}" if url else "(生成完成,但未能提取媒体地址)"
media_type = "image" if s.startswith("<img") else "video"
if not url:
return "(生成完成,但未能提取媒体地址)"
# IM Bot 路径此前完全不记账 → 补写媒体消耗,驾驶舱才看得到图片/视频数据
_log_media_usage(db, user_id, ai_model, media_type, prompt)
return {"__media__": True, "media_type": media_type, "url": url}
# 媒体生成失败:_generate_media 已返回友好中文(如限频/队列繁忙),
# 直接透传,绝不把原始提示词/标签/JSON 透传给用户
if s.startswith("⚠️") or s.startswith("(媒体"):
return s
return "(媒体生成未能返回有效内容,请重试)"
return result
# ===== 2) 文本回复 + 技能自动发现(Issue 8)=====
ai_model = resolve_auto_model("text", db)