FastAPI-Backend-Models / services /mcp_service.py
malek-messaoudii
feat: Update generate_speech function to use gTTS backend with MP3 format and modify voice parameter to accept language codes. Clean up tts_service.py by removing unused GROQ API key checks and related code.
a61d0cb
raw
history blame
4.54 kB
"""Service pour initialiser le serveur MCP avec FastMCP"""
from mcp.server.fastmcp import FastMCP
from typing import Dict, Any, Optional
import logging
from fastapi import FastAPI
from services.stance_model_manager import stance_model_manager
from services.label_model_manager import kpa_model_manager
from services.stt_service import speech_to_text
from services.tts_service import text_to_speech
from services.generate_model_manager import generate_model_manager
from services.topic_service import topic_service
from services.chat_service import generate_chat_response
logger = logging.getLogger(__name__)
# Créer l'instance FastMCP
mcp_server = FastMCP("NLP-Debater-MCP", json_response=True, stateless_http=False) # Stateful pour sessions
# Tools (inchangés, OK)
@mcp_server.tool()
def detect_stance(topic: str, argument: str) -> Dict[str, Any]:
if not stance_model_manager.model_loaded:
raise ValueError("Modèle stance non chargé")
result = stance_model_manager.predict(topic, argument)
return {
"predicted_stance": result["predicted_stance"],
"confidence": result["confidence"],
"probability_con": result["probability_con"],
"probability_pro": result["probability_pro"]
}
@mcp_server.tool()
def match_keypoint_argument(argument: str, key_point: str) -> Dict[str, Any]:
if not kpa_model_manager.model_loaded:
raise ValueError("Modèle KPA non chargé")
result = kpa_model_manager.predict(argument, key_point)
return {
"prediction": result["prediction"],
"label": result["label"],
"confidence": result["confidence"],
"probabilities": result["probabilities"]
}
@mcp_server.tool()
def transcribe_audio(audio_path: str) -> str:
return speech_to_text(audio_path)
@mcp_server.tool()
def generate_speech(text: str, voice: str = "en", format: str = "mp3") -> str:
"""
Generate speech using the free gTTS backend (MP3 only).
'voice' expects a language code (e.g., 'en', 'fr').
"""
return text_to_speech(text, voice, format)
@mcp_server.tool()
def generate_argument(topic: str, position: str) -> Dict[str, Any]:
"""Generate an argument for a given topic and position"""
if not generate_model_manager.model_loaded:
raise ValueError("Modèle de génération non chargé")
argument = generate_model_manager.generate(topic=topic, position=position)
return {
"topic": topic,
"position": position,
"argument": argument
}
@mcp_server.tool()
def extract_topic(text: str) -> Dict[str, Any]:
"""Extract a topic from the given text/argument"""
if not topic_service.initialized:
topic_service.initialize()
topic = topic_service.extract_topic(text)
return {
"text": text,
"topic": topic
}
@mcp_server.tool()
def voice_chat(user_input: str, conversation_id: Optional[str] = None) -> Dict[str, Any]:
"""Generate a chatbot response for voice chat (English only)"""
response_text = generate_chat_response(
user_input=user_input,
conversation_id=conversation_id
)
return {
"user_input": user_input,
"conversation_id": conversation_id,
"response": response_text
}
@mcp_server.resource("debate://prompt")
def get_debate_prompt() -> str:
return "Tu es un expert en débat. Génère 3 arguments PRO pour le topic donné. Sois concis et persuasif."
# Health tool (enregistré avant l'initialisation)
@mcp_server.tool()
def health_check() -> Dict[str, Any]:
"""Health check pour le serveur MCP"""
try:
# Liste hardcodée pour éviter les problèmes avec list_tools()
tool_names = [
"detect_stance",
"match_keypoint_argument",
"transcribe_audio",
"generate_speech",
"generate_argument",
"extract_topic",
"voice_chat",
"health_check"
]
except Exception:
tool_names = []
return {"status": "healthy", "tools": tool_names}
def init_mcp_server(app: FastAPI) -> None:
"""
Initialise et monte le serveur MCP sur l'app FastAPI.
"""
# CORRIGÉ : Utilise streamable_http_app() qui retourne l'ASGI app
mcp_app = mcp_server.streamable_http_app() # L'ASGI app pour mounting (gère /health, /tools, etc. nativement)
# Monte à /api/v1/mcp - FastAPI gère le lifespan auto
app.mount("/api/v1/mcp", mcp_app)
logger.info("✓ Serveur MCP monté sur /api/v1/mcp avec tools NLP/STT/TTS")