ForcePilot/backend/package/yuxi/channels/adapters/mattermost/vision.py
Kris 002d601d1b feat(mattermost): 实现完整的 Mattermost 适配器模块
新增 Mattermost 渠道完整实现,包含适配器核心、消息处理、交互回调、命令支持、安全校验、多账号管理等功能,支持机器人消息发送、交互按钮、命令注册、投票功能以及配置动态修改等特性。
2026-05-12 00:46:12 +08:00

122 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from typing import Any
from yuxi.utils.logging_config import logger
async def analyze_image(
adapter: Any,
file_id: str,
prompt: str = "Describe this image",
) -> str | None:
"""分析 Mattermost 图片 — 下载图片后通过 AI 视觉模型分析。
返回分析文本,失败返回 None。
"""
try:
image_data = await adapter.download_media(file_id)
except Exception as e:
logger.error(f"[Mattermost] Failed to download image for analysis: {e}")
return None
return await _call_vision_api(adapter, image_data, prompt)
async def analyze_attachment(
adapter: Any,
file_id: str,
file_name: str = "",
) -> str | None:
"""分析 Mattermost 附件 — 通用附件分析入口。"""
try:
attachment_data = await adapter.download_media(file_id)
except Exception as e:
logger.error(f"[Mattermost] Failed to download attachment for analysis: {e}")
return None
prompt = f"Analyze this file: {file_name}" if file_name else "Analyze this file"
return await _call_vision_api(adapter, attachment_data, prompt)
async def _call_vision_api(adapter: Any, data: bytes, prompt: str) -> str | None:
"""调用 AI 视觉 API 分析内容。"""
try:
import base64
base64_data = base64.b64encode(data).decode()
vision_config = (adapter.config or {}).get("vision", {})
provider = vision_config.get("provider", "openai")
model = vision_config.get("model", "gpt-4o")
if provider == "openai":
import openai
client = openai.AsyncOpenAI(api_key=vision_config.get("api_key", ""))
response = await client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_data}",
},
},
],
},
],
max_tokens=500,
)
return response.choices[0].message.content if response.choices else None
logger.warning(f"[Mattermost] Unsupported vision provider: {provider}")
return None
except ImportError:
logger.warning("[Mattermost] OpenAI library not installed for vision analysis")
return None
except Exception as e:
logger.error(f"[Mattermost] Vision API call failed: {e}")
return None
async def synthesize_speech(
adapter: Any,
text: str,
voice: str = "alloy",
) -> bytes | None:
"""TTS 语音合成 — 将文本转换为语音。
返回音频数据 bytes失败返回 None。
"""
try:
tts_config = (adapter.config or {}).get("tts", {})
provider = tts_config.get("provider", "openai")
model = tts_config.get("model", "tts-1")
if provider == "openai":
import openai
client = openai.AsyncOpenAI(api_key=tts_config.get("api_key", ""))
response = await client.audio.speech.create(
model=model,
voice=voice,
input=text,
)
return response.content
logger.warning(f"[Mattermost] Unsupported TTS provider: {provider}")
return None
except ImportError:
logger.warning("[Mattermost] OpenAI library not installed for TTS")
return None
except Exception as e:
logger.error(f"[Mattermost] TTS synthesis failed: {e}")
return None