Quoota_RAG / rag24.py
Malaji71's picture
Update rag24.py
7086144 verified
"""
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)