Skip to main content
Glama
document_service.py7.71 kB
""" Trusty Sign - Document Analysis Service Analyzes contracts and documents using LLM """ import logging from typing import Dict, Any, List, Optional from dataclasses import dataclass from src.llm_core.client import IRISClient logger = logging.getLogger(__name__) @dataclass class CriticalClause: """A critical clause found in contract""" type: str # PENALE, SCADENZA, LIMITAZIONE_RESPONSABILITA, VESSATORIA, RINNOVO_TACITO risk_level: str # HIGH, MEDIUM, LOW text: str location: str # e.g. "Punto 7.3, Pagina 8" suggestion: str @dataclass class ContractAnalysis: """Full contract analysis result""" document_type: str summary: str parties: List[Dict[str, str]] value: Optional[str] duration: Optional[str] deadlines: List[Dict[str, str]] obligations: Dict[str, List[str]] critical_clauses: List[CriticalClause] class DocumentService: """Service for document analysis using LLM""" def __init__(self, iris_client: IRISClient): """ Initialize document service Args: iris_client: IRISClient instance for LLM calls """ self.iris = iris_client async def analyze_contract( self, pdf_text: str, session_id: str ) -> Dict[str, Any]: """ Perform full contract analysis with LLM Args: pdf_text: Extracted text from PDF session_id: Session ID for conversation tracking Returns: Analysis dictionary with contract details """ try: logger.info(f"Analyzing contract (session={session_id})") # Truncate text if too long (max ~8000 chars for context) truncated_text = pdf_text[:8000] if len(pdf_text) > 8000 else pdf_text prompt = self._create_analysis_prompt(truncated_text) analysis = await self.iris.chat( session_id=session_id, message=prompt, max_tokens=1500 ) logger.info(f"Contract analysis completed (session={session_id})") return {"summary": analysis} except Exception as e: logger.error(f"Error analyzing contract: {e}") return { "summary": f"⚠️ Errore durante l'analisi: {str(e)}", "error": str(e) } async def extract_critical_clauses( self, pdf_text: str, session_id: str ) -> str: """ Extract and analyze critical clauses from contract Args: pdf_text: Extracted text from PDF session_id: Session ID for conversation tracking Returns: Formatted string with critical clauses analysis """ try: logger.info(f"Extracting critical clauses (session={session_id})") # Truncate text if too long truncated_text = pdf_text[:8000] if len(pdf_text) > 8000 else pdf_text prompt = self._create_clauses_prompt(truncated_text) clauses = await self.iris.chat( session_id=session_id, message=prompt, max_tokens=2000 ) logger.info(f"Critical clauses extracted (session={session_id})") return clauses except Exception as e: logger.error(f"Error extracting clauses: {e}") return f"⚠️ Errore durante l'estrazione delle clausole: {str(e)}" async def analyze_document_full( self, pdf_text: str, session_id: str ) -> str: """ Perform complete document analysis (summary + critical clauses) Args: pdf_text: Extracted text from PDF session_id: Session ID Returns: Complete analysis as formatted string """ try: # Get contract analysis analysis = await self.analyze_contract(pdf_text, session_id) # Get critical clauses clauses = await self.extract_critical_clauses(pdf_text, session_id) # Combine results full_analysis = f""" 📄 **ANALISI COMPLETATA** {analysis.get('summary', 'Analisi non disponibile')} --- 🔍 **CLAUSOLE CRITICHE** {clauses} --- 💬 Vuoi procedere con la firma o preferisci approfondire qualcosa? """ return full_analysis except Exception as e: logger.error(f"Error in full analysis: {e}") return f"⚠️ Errore durante l'analisi completa: {str(e)}" def _create_analysis_prompt(self, pdf_text: str) -> str: """Create prompt for contract analysis""" return f""" Sei un esperto legale. Analizza questo contratto e fornisci un'analisi strutturata. **ISTRUZIONI**: 1. Leggi attentamente il testo 2. Identifica il tipo di contratto 3. Estrai informazioni chiave 4. Fornisci summary esecutivo **FORMATO RISPOSTA**: 📊 **TIPO CONTRATTO**: [tipo contratto] 📝 **SUMMARY** (max 100 parole): [descrizione breve di cosa prevede il contratto] 💼 **PARTI COINVOLTE**: - Cliente: [nome] - Fornitore/Controparte: [nome] 💰 **VALORE**: [importo se presente] 📅 **DURATA**: [periodo di validità] ⚠️ **SCADENZE IMPORTANTI**: - [data]: [cosa scade/avviene] ✅ **OBBLIGHI PRINCIPALI**: 1. Cliente deve: [obblighi] 2. Fornitore deve: [obblighi] **TESTO CONTRATTO**: {pdf_text} """ def _create_clauses_prompt(self, pdf_text: str) -> str: """Create prompt for critical clauses extraction""" return f""" Analizza il seguente contratto e identifica CLAUSOLE CRITICHE che richiedono particolare attenzione. **CERCA QUESTE TIPOLOGIE**: 1. 💰 **PENALI**: Clausole con sanzioni economiche (es: "penale", "multa", "risarcimento") 2. ⏰ **SCADENZE PERENTORIE**: Date improrogabili (es: "termine perentorio", "entro e non oltre") 3. 🚫 **LIMITAZIONI RESPONSABILITÀ**: Cap su responsabilità (es: "limitata a", "massimo", "non superiore") 4. ⚖️ **CLAUSOLE VESSATORIE**: Sbilanciamento contrattuale (es: "a insindacabile giudizio", "senza preavviso") 5. 📜 **RINNOVO TACITO**: Rinnovi automatici (es: "tacito rinnovo", "automaticamente rinnovato") **FORMATO RISPOSTA**: Per ogni clausola trovata, usa questo formato: ⚠️ **[TIPO CLAUSOLA]** - Punto [X.Y] 📍 Testo: "[citazione esatta dalla clausola]" 🎯 Rischio: [🔴 ALTO / 🟡 MEDIO / 🟢 BASSO] 💡 Suggerimento: [cosa fare - es: "Valuta negoziazione", "Imposta reminder", etc.] --- **ESEMPI**: ⚠️ **PENALE** - Punto 7.3 📍 Testo: "In caso di ritardo superiore a 30 giorni, il Fornitore riconoscerà una penale pari al 15% del valore contrattuale" 🎯 Rischio: 🔴 ALTO 💡 Suggerimento: Penale del 15% è superiore alla media di mercato (8-10%). Valuta negoziazione per ridurre al 10% o inserire cap massimo. ⚠️ **SCADENZA PERENTORIA** - Punto 12.1 📍 Testo: "Il preavviso di recesso deve essere comunicato con almeno 90 giorni di anticipo rispetto alla scadenza" 🎯 Rischio: 🟡 MEDIO 💡 Suggerimento: Imposta reminder 120 giorni prima della scadenza contratto se intendi recedere. --- **ATTENZIONE**: - Rispondi SOLO con le clausole trovate nel formato indicato - Se non trovi clausole critiche, scrivi "✅ Nessuna clausola particolarmente critica rilevata" - Non inventare clausole che non ci sono - Sii preciso nelle citazioni **TESTO CONTRATTO**: {pdf_text} """

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilvolodel/iris-legacy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server