106 lines
4.5 KiB
Python
106 lines
4.5 KiB
Python
import httpx
|
|
import json
|
|
import logging
|
|
import re
|
|
from app.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
PROMPTS = {
|
|
"minutes": (
|
|
"Voce e um assistente especializado em reunioes corporativas. "
|
|
"Com base na transcricao a seguir, gere uma ata estruturada em JSON contendo: "
|
|
"title (string), participants (array de objetos com name e role), "
|
|
"agenda (array de strings), decisions (array de strings), "
|
|
"action_items (array de objetos com description, responsible e deadline), "
|
|
"next_steps (array de strings), open_points (array de strings). "
|
|
"Retorne APENAS o JSON valido, sem texto adicional. "
|
|
"Transcricao: {transcription}"
|
|
),
|
|
"sentiment": (
|
|
"Analise o tom emocional desta reuniao e retorne um JSON com: "
|
|
"overall_sentiment (positive/neutral/negative), "
|
|
"timeline (array de objetos com time_range, sentiment e notes), "
|
|
"participants_sentiment (array de objetos com speaker, sentiment e details), "
|
|
"tension_moments (array de strings), "
|
|
"consensus_moments (array de strings), "
|
|
"participation_metrics (array de objetos com speaker, talk_percentage e interventions_count). "
|
|
"Retorne APENAS o JSON valido. "
|
|
"Transcricao: {transcription}"
|
|
),
|
|
"psychological": (
|
|
"Analise os padroes comportamentais dos participantes e retorne um JSON com: "
|
|
"participants_profiles (array de objetos com speaker, name, communication_style, "
|
|
"leadership_tendencies, disengagement_signs, power_dynamics_role), "
|
|
"group_dynamics (string), "
|
|
"key_observations (array de strings). "
|
|
"Retorne APENAS o JSON valido. "
|
|
"Transcricao: {transcription}"
|
|
),
|
|
"communication": (
|
|
"Avalie a comunicacao dos participantes nesta reuniao e retorne um JSON com: "
|
|
"overall_score (numero de 1 a 10), "
|
|
"dimensions (objeto com clarity, active_listening, assertiveness, meeting_facilitation, "
|
|
"cada um com score e notes), "
|
|
"strengths (array de objetos com description e example), "
|
|
"improvement_areas (array de objetos com description e suggestion), "
|
|
"general_feedback (string). "
|
|
"Retorne APENAS o JSON valido. "
|
|
"Transcricao: {transcription}"
|
|
),
|
|
"summary": (
|
|
"Gere um resumo executivo desta reuniao em JSON com: "
|
|
"summary (string), "
|
|
"key_points (array de strings), "
|
|
"duration_minutes (number), "
|
|
"total_participants (number). "
|
|
"Retorne APENAS o JSON valido. "
|
|
"Transcricao: {transcription}"
|
|
),
|
|
}
|
|
|
|
|
|
async def run_analysis(analysis_type: str, transcription: dict) -> dict:
|
|
"""Run AI analysis on transcription using Ollama"""
|
|
transcription_text = json.dumps(transcription, ensure_ascii=False)
|
|
prompt_template = PROMPTS.get(analysis_type, PROMPTS["summary"])
|
|
prompt = prompt_template.replace("{transcription}", transcription_text[:8000])
|
|
|
|
logger.info(f"Running {analysis_type} analysis with Ollama model {settings.OLLAMA_MODEL}")
|
|
|
|
try:
|
|
headers = {}
|
|
if settings.OLLAMA_API_KEY:
|
|
headers["X-API-Key"] = settings.OLLAMA_API_KEY
|
|
async with httpx.AsyncClient(timeout=180.0) as client:
|
|
response = await client.post(
|
|
f"{settings.OLLAMA_URL}/api/generate",
|
|
headers=headers,
|
|
json={
|
|
"model": settings.OLLAMA_MODEL,
|
|
"prompt": prompt,
|
|
"stream": False,
|
|
"format": "json",
|
|
"options": {"temperature": 0.3},
|
|
},
|
|
)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
response_text = result.get("response", "{}")
|
|
try:
|
|
return json.loads(response_text)
|
|
except json.JSONDecodeError:
|
|
json_match = re.search(r"\{.*\}", response_text, re.DOTALL)
|
|
if json_match:
|
|
try:
|
|
return json.loads(json_match.group())
|
|
except json.JSONDecodeError:
|
|
pass
|
|
return {"raw_response": response_text, "parse_error": "Could not parse JSON"}
|
|
except httpx.ConnectError as e:
|
|
logger.error(f"Cannot connect to Ollama at {settings.OLLAMA_URL}: {e}")
|
|
return {"error": "Ollama unavailable", "analysis_type": analysis_type}
|
|
except Exception as e:
|
|
logger.error(f"Ollama analysis error for {analysis_type}: {e}")
|
|
return {"error": str(e), "analysis_type": analysis_type}
|