IA va a tener Contexto de la primera plantilal de las Inspecciones backend 1.0.42 frontend 1.0.40
This commit is contained in:
@@ -1520,6 +1520,7 @@ def delete_ai_configuration(
|
|||||||
async def analyze_image(
|
async def analyze_image(
|
||||||
file: UploadFile = File(...),
|
file: UploadFile = File(...),
|
||||||
question_id: int = None,
|
question_id: int = None,
|
||||||
|
inspection_id: int = None,
|
||||||
custom_prompt: str = None,
|
custom_prompt: str = None,
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
current_user: models.User = Depends(get_current_user)
|
current_user: models.User = Depends(get_current_user)
|
||||||
@@ -1527,6 +1528,7 @@ async def analyze_image(
|
|||||||
"""
|
"""
|
||||||
Analiza una imagen usando IA para sugerir respuestas
|
Analiza una imagen usando IA para sugerir respuestas
|
||||||
Usa la configuración de IA activa (OpenAI o Gemini)
|
Usa la configuración de IA activa (OpenAI o Gemini)
|
||||||
|
Incluye contexto del vehículo si se proporciona inspection_id
|
||||||
"""
|
"""
|
||||||
# Obtener configuración de IA activa
|
# Obtener configuración de IA activa
|
||||||
ai_config = db.query(models.AIConfiguration).filter(
|
ai_config = db.query(models.AIConfiguration).filter(
|
||||||
@@ -1550,6 +1552,22 @@ async def analyze_image(
|
|||||||
if question_id:
|
if question_id:
|
||||||
question_obj = db.query(models.Question).filter(models.Question.id == question_id).first()
|
question_obj = db.query(models.Question).filter(models.Question.id == question_id).first()
|
||||||
|
|
||||||
|
# Obtener contexto del vehículo si se proporciona inspection_id
|
||||||
|
vehicle_context = ""
|
||||||
|
if inspection_id:
|
||||||
|
inspection = db.query(models.Inspection).filter(models.Inspection.id == inspection_id).first()
|
||||||
|
if inspection:
|
||||||
|
vehicle_context = f"""
|
||||||
|
INFORMACIÓN DEL VEHÍCULO INSPECCIONADO:
|
||||||
|
- Marca: {inspection.vehicle_brand}
|
||||||
|
- Modelo: {inspection.vehicle_model}
|
||||||
|
- Año: {inspection.vehicle_year or 'No especificado'}
|
||||||
|
- Placa: {inspection.vehicle_plate}
|
||||||
|
- Kilometraje: {inspection.mileage} km
|
||||||
|
- Cliente: {inspection.client_name}
|
||||||
|
- OR/Orden: {inspection.or_number}
|
||||||
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Construir prompt dinámico basado en la pregunta específica
|
# Construir prompt dinámico basado en la pregunta específica
|
||||||
if question_obj:
|
if question_obj:
|
||||||
@@ -1558,6 +1576,8 @@ async def analyze_image(
|
|||||||
# Prompt 100% personalizado por el administrador
|
# Prompt 100% personalizado por el administrador
|
||||||
system_prompt = f"""Eres un mecánico experto realizando una inspección vehicular.
|
system_prompt = f"""Eres un mecánico experto realizando una inspección vehicular.
|
||||||
|
|
||||||
|
{vehicle_context}
|
||||||
|
|
||||||
INSTRUCCIONES ESPECÍFICAS PARA ESTA PREGUNTA:
|
INSTRUCCIONES ESPECÍFICAS PARA ESTA PREGUNTA:
|
||||||
{custom_prompt}
|
{custom_prompt}
|
||||||
|
|
||||||
@@ -1565,6 +1585,7 @@ PREGUNTA A RESPONDER: "{question_obj.text}"
|
|||||||
Sección: {question_obj.section}
|
Sección: {question_obj.section}
|
||||||
|
|
||||||
Analiza la imagen siguiendo EXACTAMENTE las instrucciones proporcionadas arriba.
|
Analiza la imagen siguiendo EXACTAMENTE las instrucciones proporcionadas arriba.
|
||||||
|
Considera el kilometraje, marca y modelo del vehículo para dar un análisis más preciso.
|
||||||
|
|
||||||
VALIDACIÓN DE IMAGEN:
|
VALIDACIÓN DE IMAGEN:
|
||||||
- Si la imagen NO corresponde al contexto de la pregunta (por ejemplo, si piden luces pero muestran motor), indica en "recommendation" que deben cambiar la foto
|
- Si la imagen NO corresponde al contexto de la pregunta (por ejemplo, si piden luces pero muestran motor), indica en "recommendation" que deben cambiar la foto
|
||||||
@@ -1573,7 +1594,7 @@ VALIDACIÓN DE IMAGEN:
|
|||||||
Responde en formato JSON:
|
Responde en formato JSON:
|
||||||
{{
|
{{
|
||||||
"status": "ok|minor|critical",
|
"status": "ok|minor|critical",
|
||||||
"observations": "Análisis específico según el prompt personalizado",
|
"observations": "Análisis específico según el prompt personalizado, considerando el vehículo {inspection.vehicle_brand if inspection_id else ''}",
|
||||||
"recommendation": "Si la imagen no es apropiada, indica 'Por favor tome una foto de [componente correcto]'. Si es apropiada, da recomendación técnica.",
|
"recommendation": "Si la imagen no es apropiada, indica 'Por favor tome una foto de [componente correcto]'. Si es apropiada, da recomendación técnica.",
|
||||||
"confidence": 0.0-1.0
|
"confidence": 0.0-1.0
|
||||||
}}"""
|
}}"""
|
||||||
@@ -1585,11 +1606,14 @@ Responde en formato JSON:
|
|||||||
|
|
||||||
system_prompt = f"""Eres un mecánico experto realizando una inspección vehicular.
|
system_prompt = f"""Eres un mecánico experto realizando una inspección vehicular.
|
||||||
|
|
||||||
|
{vehicle_context}
|
||||||
|
|
||||||
PREGUNTA ESPECÍFICA A RESPONDER: "{question_text}"
|
PREGUNTA ESPECÍFICA A RESPONDER: "{question_text}"
|
||||||
Sección: {section}
|
Sección: {section}
|
||||||
|
|
||||||
Analiza la imagen ÚNICAMENTE para responder esta pregunta específica.
|
Analiza la imagen ÚNICAMENTE para responder esta pregunta específica.
|
||||||
Sé directo y enfócate solo en lo que la pregunta solicita.
|
Sé directo y enfócate solo en lo que la pregunta solicita.
|
||||||
|
Considera el kilometraje y características del vehículo para contextualizar tu análisis.
|
||||||
|
|
||||||
VALIDACIÓN DE IMAGEN:
|
VALIDACIÓN DE IMAGEN:
|
||||||
- Si la imagen NO corresponde al contexto de la pregunta, indica en "recommendation" que deben cambiar la foto
|
- Si la imagen NO corresponde al contexto de la pregunta, indica en "recommendation" que deben cambiar la foto
|
||||||
@@ -1613,19 +1637,23 @@ IMPORTANTE:
|
|||||||
user_message = f"Inspecciona la imagen y responde específicamente: {question_obj.text}"
|
user_message = f"Inspecciona la imagen y responde específicamente: {question_obj.text}"
|
||||||
else:
|
else:
|
||||||
# Fallback para análisis general
|
# Fallback para análisis general
|
||||||
system_prompt = """Eres un experto mecánico automotriz. Analiza la imagen y proporciona:
|
system_prompt = f"""Eres un experto mecánico automotriz.
|
||||||
|
|
||||||
|
{vehicle_context}
|
||||||
|
|
||||||
|
Analiza la imagen y proporciona:
|
||||||
1. Estado del componente (bueno/regular/malo)
|
1. Estado del componente (bueno/regular/malo)
|
||||||
2. Nivel de criticidad (ok/minor/critical)
|
2. Nivel de criticidad (ok/minor/critical)
|
||||||
3. Observaciones técnicas breves
|
3. Observaciones técnicas breves
|
||||||
4. Recomendación de acción
|
4. Recomendación de acción
|
||||||
|
|
||||||
Responde en formato JSON:
|
Responde en formato JSON:
|
||||||
{
|
{{
|
||||||
"status": "ok|minor|critical",
|
"status": "ok|minor|critical",
|
||||||
"observations": "descripción técnica",
|
"observations": "descripción técnica",
|
||||||
"recommendation": "acción sugerida",
|
"recommendation": "acción sugerida",
|
||||||
"confidence": 0.0-1.0
|
"confidence": 0.0-1.0
|
||||||
}"""
|
}}"""
|
||||||
user_message = "Analiza este componente del vehículo para la inspección general."
|
user_message = "Analiza este componente del vehículo para la inspección general."
|
||||||
|
|
||||||
if ai_config.provider == "openai":
|
if ai_config.provider == "openai":
|
||||||
|
|||||||
@@ -3069,6 +3069,11 @@ function InspectionModal({ checklist, user, onClose, onComplete }) {
|
|||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
formData.append('question_id', question.id.toString())
|
formData.append('question_id', question.id.toString())
|
||||||
|
|
||||||
|
// Include inspection_id for vehicle context
|
||||||
|
if (inspectionId) {
|
||||||
|
formData.append('inspection_id', inspectionId.toString())
|
||||||
|
}
|
||||||
|
|
||||||
// Include custom prompt if available
|
// Include custom prompt if available
|
||||||
if (question.ai_prompt) {
|
if (question.ai_prompt) {
|
||||||
formData.append('custom_prompt', question.ai_prompt)
|
formData.append('custom_prompt', question.ai_prompt)
|
||||||
|
|||||||
28
migrations/add_ai_analysis_if_not_exists.sql
Normal file
28
migrations/add_ai_analysis_if_not_exists.sql
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-- Migración: Asegurar que ai_analysis existe en la tabla answers
|
||||||
|
-- Fecha: 2025-11-26
|
||||||
|
-- Descripción: Agrega la columna ai_analysis si no existe (para guardar el resultado del análisis de IA)
|
||||||
|
|
||||||
|
-- Agregar columna ai_analysis si no existe
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_name = 'answers'
|
||||||
|
AND column_name = 'ai_analysis'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE answers ADD COLUMN ai_analysis JSONB;
|
||||||
|
COMMENT ON COLUMN answers.ai_analysis IS 'Resultado del análisis de IA: {status, observations, recommendation, confidence, model, provider}';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Verificar que la columna existe
|
||||||
|
SELECT
|
||||||
|
column_name,
|
||||||
|
data_type,
|
||||||
|
is_nullable,
|
||||||
|
column_default
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = 'answers'
|
||||||
|
AND column_name = 'ai_analysis';
|
||||||
|
|
||||||
|
SELECT '✅ Columna ai_analysis verificada/creada en tabla answers' as status;
|
||||||
Reference in New Issue
Block a user