ForcePilot/backend/package/yuxi/channels/adapters/signal/media_vision.py
Kris 8dc86766f1 feat(channels/signal): 新增Signal渠道适配器完整实现
新增了完整的Signal渠道适配器实现,包含RPC客户端、守护进程管理、安全策略、消息处理、安装配置工具等全套功能,支持通过signal-cli与Signal网络进行通信,包含账户管理、消息收发、反应处理、媒体分析、健康检查等能力。
2026-05-12 00:48:25 +08:00

58 lines
2.0 KiB
Python

from __future__ import annotations
import base64
import logging
from typing import Any
logger = logging.getLogger(__name__)
VISION_SYSTEM_PROMPT = (
"You are a media analyst. Describe the content of the provided media concisely. "
"For images: describe what you see. "
"For videos: note it's a video and describe visible elements. "
"Keep responses under 200 characters."
)
class MediaVisionAnalyzer:
def __init__(self, llm_call_fn: Any, enabled: bool = True):
self._llm_call = llm_call_fn
self._enabled = enabled
async def analyze_image(self, image_data: bytes, mime_type: str = "image/jpeg") -> str | None:
if not self._enabled or not self._llm_call:
return None
try:
b64 = base64.b64encode(image_data).decode("utf-8")
result = await self._llm_call(
messages=[
{"role": "system", "content": VISION_SYSTEM_PROMPT},
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this media content briefly."},
{"type": "image_url", "image_url": {"url": f"data:{mime_type};base64,{b64}"}},
],
},
]
)
return result.get("content", "") if isinstance(result, dict) else str(result)
except Exception:
logger.exception("Media vision analysis failed")
return None
async def analyze_attachment(
self,
data: bytes,
filename: str | None = None,
mime_type: str = "application/octet-stream",
) -> str | None:
if mime_type.startswith("image/"):
return await self.analyze_image(data, mime_type)
if mime_type.startswith("video/"):
return f"[video: {filename or 'unnamed'}]"
if mime_type.startswith("audio/"):
return f"[audio: {filename or 'unnamed'}]"
return f"[file: {filename or 'unnamed'}]"