""" IM Bot 真实 LLM 调用。 原实现位于 channels.py(通用频道管理模块),该模块已移除。 为保持 IM Bot(微信机器人等)正常生成回复,将 _call_real_llm 迁移至此独立模块。 行为(对齐 AI 聊天): - Issue 7:图像/视频/语音意图优先走平台媒体模型(与 AI 聊天同一套 Auto 路由), 不再对"制作图片"这类请求只回文本。 - Issue 8:默认 Auto 模型;每轮先自动发现本账号已安装且平台已部署的技能, 多个适用时由模型自行判断选 1 个最优,通过 function calling 执行。 - 2026-07-15:修复 trust_env=False + proxy 处理,避免容器坏代理导致调用失败; 媒体生成前先经 _optimize_media_prompt 精炼提示词,提升 AGNES 生成质量。 """ import asyncio import json import re as _re from typing import Optional from urllib.parse import urlparse as _urlparse import httpx from sqlalchemy.orm import Session from ..capability_registry import resolve_auto_model from ..models import AIModel, ModelProvider def _proxy_for_url(url: str) -> str | None: """按目标域名选择是否走代理(与 chat.py 同逻辑)。 对 AGNES 等国内域名返回 None(直连),平台自有域名直连,其余走智能路由代理。 """ import os host = (_urlparse(url).hostname or "").lower() if "agnes-ai.com" in host or "agnes-ai.space" in host: return None if "qihuyun.com" in host: return None return os.environ.get("HTTPS_PROXY") or os.environ.get("HTTP_PROXY") or "http://172.18.0.1:7890" def _run_async(coro): """在同步上下文中运行协程,兼容「无事件循环」与「已有事件循环」两种场景。 IM 个人微信在独立线程中调用(无事件循环)→ asyncio.run; IM 多平台 Webhook 可能在 FastAPI 协程内调用(已有事件循环)→ 丢到线程池执行。 """ try: loop = asyncio.get_running_loop() except RuntimeError: loop = None if loop is not None and loop.is_running(): import concurrent.futures with concurrent.futures.ThreadPoolExecutor(1) as ex: return ex.submit(lambda: asyncio.run(coro)).result() return asyncio.run(coro) def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im", user_id: str = None) -> str: """调用七虎AI 生成回复,供 IM Bot 复用。支持媒体意图路由与已安装技能自动发现。""" try: from app.api.chat import ( _generate_media, detect_media_intent, _discover_installed_skills, _build_system_prompt, _execute_skill_tool, ) # ===== 1) 媒体意图路由(Issue 7)===== intent = detect_media_intent(prompt) if intent: ai_model = resolve_auto_model(intent, db) if ai_model: try: result = _run_async(_generate_media(db, ai_model, prompt, user_id)) except Exception as e: result = f"(媒体生成失败:{e})" if result: # IM 不渲染 HTML,把 /