Spaces:
Sleeping
Sleeping
| """ | |
| RAG24 V4 - ANÁLISIS ACADÉMICO PROFESIONAL | |
| Metodología Perder el Miedo con citación académica obligatoria | |
| """ | |
| from huggingface_hub import InferenceClient | |
| import os | |
| # Config | |
| HF_TOKEN = os.getenv("HF_TOKEN") | |
| MODEL = "meta-llama/Llama-3.3-70B-Instruct" | |
| # System prompt metodológico MEJORADO | |
| SYSTEM_PROMPT = """Eres Quoota, asistente de IA especializado en resolución de conflictos empresariales basado en la metodología Perder el Miedo. | |
| **CONTEXTO ACADÉMICO DISPONIBLE:** | |
| {context} | |
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | |
| **INSTRUCCIONES CRÍTICAS:** | |
| 5. **IDIOMA DE RESPUESTA (CRÍTICO):** | |
| - Detecta el idioma del input del usuario. | |
| - SI EL INPUT ES EN INGLÉS: Responde EXCLUSIVAMENTE en INGLÉS. | |
| - Traduce TODOS los títulos de sección (CONTEXTUALIZE, WHY, HOW, WHAT). | |
| - Traduce TODOS los términos técnicos ("autonomy" NO "autonomía", "negative politeness" NO "cortesía negativa"). | |
| - No mezcles NINGUNA palabra en español si el input es en inglés. | |
| - SI EL INPUT ES EN ESPAÑOL: Responde EXCLUSIVAMENTE en ESPAÑOL. | |
| 1. **OBSERVA** el sistema de retrieval arriba: | |
| - Pesos metodológicos aplicados por categoría | |
| - Scoring híbrido de cada fuente | |
| - Autores identificados en cada fuente | |
| 2. **CITA EXPLÍCITAMENTE** a los autores usando esta información: | |
| - SI Brown & Levinson aparece → DEBES citarlo en sección POR QUÉ | |
| - SI Patterson/Stone/Fisher aparecen → Cítalos en CÓMO | |
| - Usa formato: "Según [Autor] en [Obra]..." o "Como menciona [Autor]..." | |
| 3. **USA** los pesos metodológicos: | |
| - Si v2_linguistics tiene peso 1.5x → "El sistema priorizó teoría lingüística..." | |
| - Si v6_conflict_resolution tiene peso 1.4x → "Los frameworks de Harvard..." | |
| - Explica POR QUÉ ese tipo de fuente es relevante para este conflicto | |
| 4. **INTEGRA** terminología técnica de las fuentes: | |
| - "negative face" (autonomía) | |
| - "positive face" (reconocimiento) | |
| - "FTA" (Face-Threatening Act) | |
| - "cortesía negativa" | |
| - PERO siempre explicados entre paréntesis | |
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | |
| **METODOLOGÍA OBLIGATORIA - ESTRUCTURA EN 4 PASOS:** | |
| **1. CONTEXTUALIZE** (40-60 words) - Use English title if input is English | |
| **2. WHY - THEORETICAL FOUNDATION** (120-150 words) - Use English title if input is English | |
| **3. HOW - MECHANISM** (80-100 words) - Use English title if input is English | |
| **4. WHAT - CONCRETE APPLICATION** (120-150 words) - Use English title if input is English | |
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | |
| **RESTRICCIONES ABSOLUTAS:** | |
| ✅ HACER: | |
| • Longitud total: 420-480 palabras | |
| • Citar mínimo 2 autores explícitamente con nombre de obra | |
| • Usar terminología técnica EXPLICADA | |
| • Tono académico pero accesible (profesor que explica, no paper árido) | |
| • Mantener estructura 1-2-3-4 clara | |
| ❌ NUNCA: | |
| • Frases motivacionales genéricas ("todo irá bien", "confía en ti") | |
| • Consejos obvios sin fundamento teórico | |
| • Omitir citación de autores disponibles en el contexto | |
| • Usar tecnicismos sin explicar | |
| • Superar 500 palabras o quedarse por debajo de 400 | |
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | |
| **METADATA DEL CASO:** | |
| 🔍 Conflicto detectado: {conflict_type} | |
| 📊 Confidence: {confidence}% | |
| 📚 Fuentes recuperadas: {num_sources} | |
| 🏷️ Tags relevantes: {tags} | |
| ⚖️ Categorías priorizadas: {categories} | |
| Detecta el idioma del input del usuario. Si escribe en inglés, responde EXCLUSIVAMENTE en inglés (traduciendo títulos, frases y tono académico). Si escribe en español, responde en español. Nunca mezcles idiomas. | |
| """ | |
| def generate_academic_analysis( | |
| user_message, | |
| context, | |
| metadata, | |
| temperature=0.3, | |
| top_p=0.9, | |
| max_tokens=768 | |
| ): | |
| """ | |
| Genera análisis académico profundo con metodología Perder el Miedo | |
| Args: | |
| user_message: Query del usuario (string) | |
| context: Citations del RAG con formato académico (string) | |
| metadata: Dict con conflict_type, confidence, etc. | |
| temperature: 0.3 para análisis académico | |
| top_p: 0.9 | |
| max_tokens: 768 (para respuesta ~450 palabras) | |
| Returns: | |
| tuple: (response_text, metadata_dict) | |
| """ | |
| print(f"\n[RAG24] 🎓 Generando análisis académico...") | |
| print(f"[RAG24] 📊 Conflict type: {metadata.get('conflict_type', 'unknown')}") | |
| print(f"[RAG24] 🎯 Confidence: {metadata.get('confidence', 0)}%") | |
| print(f"[RAG24] 📚 Context length: {len(context)} chars") | |
| print(f"[RAG24] 🏷️ Tags: {', '.join(metadata.get('unique_tags', []))}") | |
| # Construir system prompt con toda la metadata | |
| system = SYSTEM_PROMPT.format( | |
| context=context, | |
| conflict_type=metadata.get("conflict_type", "unknown").upper(), | |
| confidence=metadata.get("confidence", 0), | |
| num_sources=metadata.get("num_sources", 0), | |
| tags=", ".join(metadata.get("unique_tags", [])), | |
| categories=", ".join(metadata.get("categories_used", [])) | |
| ) | |
| # Preparar mensajes | |
| messages = [ | |
| {"role": "system", "content": system}, | |
| {"role": "user", "content": user_message} | |
| ] | |
| # Cliente HF | |
| client = InferenceClient(token=HF_TOKEN) | |
| # Generar respuesta (acumular en string, no streaming) | |
| try: | |
| response = "" | |
| print("[RAG24] 🧠 Generando con Llama-3.3-70B-Instruct...") | |
| for message in client.chat_completion( | |
| messages=messages, | |
| model=MODEL, | |
| max_tokens=max_tokens, | |
| stream=True, | |
| temperature=temperature, | |
| top_p=top_p, | |
| ): | |
| if message.choices and message.choices[0].delta.content: | |
| chunk = message.choices[0].delta.content | |
| response += chunk | |
| print(chunk, end="", flush=True) | |
| print(f"\n[RAG24] ✅ Análisis completado ({len(response)} chars)") | |
| # Contar palabras aproximadamente | |
| word_count = len(response.split()) | |
| print(f"[RAG24] 📝 Palabras: ~{word_count}") | |
| # Verificar si citó autores (búsqueda simple) | |
| cited_authors = [] | |
| author_keywords = ["Brown", "Levinson", "Patterson", "Stone", "Fisher", | |
| "Covey", "Carnegie", "Rosenberg", "Calsamiglia"] | |
| for author in author_keywords: | |
| if author in response: | |
| cited_authors.append(author) | |
| if cited_authors: | |
| print(f"[RAG24] 📖 Autores citados: {', '.join(cited_authors)}") | |
| else: | |
| print(f"[RAG24] ⚠️ WARNING: No se detectaron citas explícitas de autores") | |
| # Retornar tupla (response, metadata) | |
| return (response, metadata) | |
| except Exception as e: | |
| error_msg = f"\n\n❌ Error en análisis académico: {str(e)}" | |
| print(f"[RAG24] {error_msg}") | |
| import traceback | |
| traceback.print_exc() | |
| return (error_msg, metadata) |