159 lines
8.0 KiB
Python
159 lines
8.0 KiB
Python
"""
|
||
Этот файл содержит классы сервисов для выполнения различных задач:
|
||
- Получение субтитров,
|
||
- Анализ изображений,
|
||
- Суммаризация текста,
|
||
- Генерация изображений.
|
||
"""
|
||
|
||
from llm_client import CustomLLM
|
||
from typing import Dict, Any, List, Optional
|
||
import requests
|
||
|
||
# --- Сервисы для внешних операций ---
|
||
|
||
|
||
class SubtitleService:
|
||
"""
|
||
Сервис для получения текущих субтитров. Заглушки.
|
||
"""
|
||
|
||
def get_google_meet_subtitles(self) -> Optional[str]:
|
||
"""
|
||
Получает текущие, не финальные субтитры из Google Meet.
|
||
(Реализация требует интеграции с Google Workspace API или другим методом.)
|
||
"""
|
||
print("Заглушка: Получение субтитров из Google Meet...")
|
||
# TODO: Реальная интеграция с Google Meet API
|
||
return "Это текущие субтитры из Google Meet: 'Привет, как дела?'"
|
||
|
||
def get_ms_teams_subtitles(self) -> Optional[str]:
|
||
"""
|
||
Получает текущие, не финальные субтитры из Microsoft Teams.
|
||
(Реализация требует интеграции с Microsoft Graph API или другим методом.)
|
||
"""
|
||
print("Заглушка: Получение субтитров из Microsoft Teams...")
|
||
# TODO: Реальная интеграция с Microsoft Teams API
|
||
return "Это текущие субтитры из MS Teams: 'Отлично, спасибо!'"
|
||
|
||
|
||
class ImageAnalysisService:
|
||
"""
|
||
Сервис для анализа изображений с использованием Gemini Vision API.
|
||
"""
|
||
|
||
def __init__(self, llm: CustomLLM):
|
||
self.llm = llm # Ожидаем, что это будет экземпляр Gemini LLM
|
||
|
||
def analyze_image(self, image_url_or_bytes: Any, prompt: str) -> str:
|
||
"""
|
||
Анализирует изображение с помощью Gemini Vision.
|
||
`image_url_or_bytes` может быть URL, путем к файлу или байтами изображения.
|
||
LangChain Gemini Vision принимает это как часть сообщения.
|
||
"""
|
||
if "vision" not in self.llm.config.get("capabilities", []):
|
||
raise ValueError(
|
||
"Для анализа изображений требуется LLM с поддержкой 'vision' (например, Gemini)."
|
||
)
|
||
|
||
print(f"Анализ изображения: {image_url_or_bytes} с промптом: {prompt}")
|
||
|
||
# LangChain GeminiVision ожидает контент в определенном формате
|
||
# Для простоты, здесь заглушка, имитирующая обработку изображения.
|
||
# В реальной реализации, image_url_or_bytes нужно будет соответствующим образом загрузить/передать.
|
||
# Пример: [HumanMessage(content=[{"type": "text", "text": prompt}, {"type": "image_url", "image_url": {"url": image_url_or_bytes}}])]
|
||
# Или для локальных файлов: [{"type": "image_bytes", "image_bytes": {"data": base64_encoded_bytes}}]
|
||
|
||
# Поскольку у нас нет реального механизма загрузки изображения здесь,
|
||
# имитируем ответ LLM для демо-целей.
|
||
# В реальном приложении:
|
||
# messages = [
|
||
# HumanMessage(
|
||
# content=[
|
||
# {"type": "text", "text": prompt},
|
||
# {"type": "image_url", "image_url": {"url": image_url_or_bytes}} # Или image_bytes
|
||
# ]
|
||
# )
|
||
# ]
|
||
# return self.llm.invoke(messages)
|
||
|
||
return f"Заглушка анализа изображения: Изображение '{image_url_or_bytes}' содержит (по результатам анализа Gemini): 'яркий пейзаж с горами и рекой' по запросу '{prompt}'."
|
||
|
||
|
||
class SummarizationService:
|
||
"""
|
||
Сервис для суммаризации истории диалога с использованием Gemini LLM.
|
||
"""
|
||
|
||
def __init__(self, llm: CustomLLM):
|
||
self.llm = llm # Ожидаем, что это будет экземпляр Gemini LLM
|
||
|
||
def summarize_history(self,
|
||
history: List[Dict[str, str]],
|
||
num_recent_messages: int = 5) -> str:
|
||
"""
|
||
Суммирует старую историю диалога с использованием LLM.
|
||
Комбинация: последние N сообщений + суммаризация старой истории.
|
||
"""
|
||
if self.llm.provider != "google":
|
||
print(
|
||
"Предупреждение: Суммаризация рекомендуется с Gemini для лучшего качества."
|
||
)
|
||
|
||
# Последние N сообщений
|
||
recent_messages = history[-num_recent_messages:]
|
||
old_history = history[:-num_recent_messages]
|
||
|
||
summarized_old_history = ""
|
||
if old_history:
|
||
# Формируем промпт для суммаризации старой истории
|
||
old_messages_text = "\n".join(
|
||
[f"{msg['role']}: {msg['content']}" for msg in old_history])
|
||
summary_prompt = f"Суммируй следующий диалог максимально кратко, сохранив ключевые моменты и темы:\n---\n{old_messages_text}\n---"
|
||
try:
|
||
summarized_old_history = self.llm.invoke(summary_prompt)
|
||
except Exception as e:
|
||
print(f"Ошибка при суммаризации старой истории: {e}")
|
||
summarized_old_history = "Ошибка суммаризации старой истории."
|
||
|
||
# Объединяем суммированную старую историю с последними сообщениями
|
||
full_context = []
|
||
if summarized_old_history:
|
||
full_context.append(
|
||
f"Предшествующая история (краткое содержание): {summarized_old_history}"
|
||
)
|
||
for msg in recent_messages:
|
||
full_context.append(f"{msg['role']}: {msg['content']}")
|
||
|
||
return "\n".join(full_context)
|
||
|
||
|
||
class ImageGenerationService:
|
||
"""
|
||
Сервис для генерации изображений через удаленный эндпоинт (bingart).
|
||
"""
|
||
|
||
def __init__(self, base_url: str):
|
||
self.base_url = base_url
|
||
|
||
def generate_images(self, prompt: str) -> List[str]:
|
||
"""
|
||
Отправляет запрос на генерацию изображений.
|
||
"""
|
||
url = f"{self.base_url}/generate-images"
|
||
try:
|
||
# Для простоты используем GET, как указано в ТЗ, хотя POST с body более типичен для prompt
|
||
response = requests.get(url, params={"prompt": prompt})
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
if "error" in data:
|
||
raise Exception(
|
||
f"Ошибка генерации изображений: {data['error']}")
|
||
return data.get("image_urls", [])
|
||
except requests.exceptions.RequestException as e:
|
||
print(f"Ошибка при вызове сервиса генерации изображений: {e}")
|
||
raise
|
||
except Exception as e:
|
||
print(f"Не удалось получить изображения: {e}")
|
||
raise
|