RadFact es un marco para la evaluación de informes de radiología generados por modelos a partir de un informe de verdad sobre el terreno, con o sin conexión a tierra . Aprovechando las capacidades de inferencia lógica de los grandes modelos de lenguaje, RadFact no es un número único sino un conjunto de métricas que capturan aspectos de precisión y recuperación a niveles de solo texto y de texto y fundamento.
RadFact se introdujo en MAIRA-2: Generación de informes de radiología fundamentada. Aquí proporcionamos una implementación de código abierto de la métrica para facilitar su uso y desarrollo.
LLMEngine
para procesamiento paraleloPara ejecutar RadFact, sólo necesita clonar este repositorio y ejecutar el siguiente comando:
pip install .
Esto instalará el paquete radfact
y todas sus dependencias.
Alternativamente, proporcionamos un Makefile
para configurar un entorno conda con todas las dependencias. Puedes crear el ambiente con:
make miniconda
make mamba
make env
conda activate radfact
El primer paso instala miniconda, el segundo instala mamba para una resolución rápida de dependencias y el tercero crea un entorno conda llamado radfact
con todas las dependencias. Esto también instalará el paquete radfact en modo editable de forma predeterminada mediante la receta setup_packages_with_deps
(consulte Makefile). Finalmente, active el entorno para ejecutar RadFact. Esto es muy recomendable si tiene la intención de contribuir al proyecto.
Para utilizar RadFact, necesita acceso a un modelo de lenguaje grande. Primero debe configurar los puntos finales con autenticación y luego confirmar que se comportan como se esperaba utilizando nuestro script de prueba.
El LLM debe estar disponible como punto final API y ser compatible con langchain
(versión 0.1.4). Admitimos dos tipos de modelos: modelos AzureChatOpenAI y ChatOpenAI. El primero es adecuado para modelos GPT disponibles en Azure, mientras que el segundo es adecuado para modelos implementados personalizados como Llama-3 en Azure.
Admitimos los siguientes métodos de autenticación:
API_KEY
en la clave API del punto final. Usamos API_KEY
como nombre de variable de entorno predeterminado. Si usa un nombre diferente, puede especificarlo en la configuración del punto final a través de api_key_env_var_name
. Esto es especialmente útil cuando se utilizan varios puntos finales con diferentes claves API.config.json
en el directorio raíz del proyecto. Esta configuración debe tener claves subscription_id
, resource_group
y workspace_name
. Se puede descargar desde el espacio de trabajo de AzureML a través del portal. Este archivo se agrega a .gitignore
para evitar confirmaciones accidentales. Asegúrese de guardar el archivo en el directorio raíz del proyecto con el nombre config.json
como lo esperaba la clase de punto final.key_vault_secret_name
en la configuración del punto final.azure_ad_token_provider
de un modelo AzureChatOpenAI
que permite la actualización automática de tokens. Esto solo se admite en los modelos AzureChatOpenAI
. Para obtener más información sobre cómo integramos los puntos dentro de RadFact, consulte la clase LLMAPIArguments
en arguments.py que consume un objeto de punto final de la clase Endpoint
en endpoint.py.
Usamos Hydra para la gestión de configuración. Las configuraciones del punto final están en la ruta: configs/endpoints
.
Este es un ejemplo de archivo de configuración:
ENDPOINT_EXAMPLE : type : " CHAT_OPENAI " url : "" deployment_name : " llama3-70b " api_key_env_var_name : "" keyvault_secret_name : "" speed_factor : 1.0 num_parallel_processes : 10
type: "CHAT_OPENAI"
y type: "AZURE_CHAT_OPENAI"
dependiendo del modelo de punto final utilizado. Para los modelos GPT disponibles en Azure, use type: "AZURE_CHAT_OPENAI"
. Para modelos implementados personalizados como Llama-3 en Azure, use type: "CHAT_OPENAI"
.url
y probablemente deployment_name
con los valores adecuados.keyvault_secret_name
es opcional y no es obligatorio si configura la API mediante una variable de entorno. Actualice api_key_env_var_name
si utiliza un nombre de variable de entorno diferente para la clave API que el "API_KEY"
predeterminado. Cuando utilice varios puntos finales, especifique api_key_env_var_name
diferente para cada punto final.speed_factor
se utiliza cuando hay más de un punto final disponible. Esto le permite especificar la velocidad relativa del punto final en comparación con los demás, que se utiliza para fragmentar los datos entre los puntos finales proporcionalmente.num_parallel_processes
se usa para especificar la cantidad de procesos paralelos que se usarán al consultar un punto final específico. Todas las solicitudes se procesan secuencialmente a menos que num_parallel_processes
se establezca en un valor mayor que 1, lo que permite el procesamiento paralelo. Como se indicó anteriormente, cuando se utiliza RadFact para la evaluación de informes no fundamentados , por ejemplo narrativos, RadFact primero convierte los informes en una lista de frases. Usamos un LLM para este paso, pero no es necesario que sea el mismo LLM que se usa para la verificación de vinculación. Puede especificar qué punto final (por lo tanto, LLM) se utiliza para cada tarea en las siguientes configuraciones, en override endpoints:
:
configs/report_to_phrases.yaml
: conversión de informe a lista de frases. En MAIRA-2, utilizamos GPT-4 para esto, que se puede consultar como un modelo AzureChatOpenAI.configs/radfact.yaml
- verificación de vinculación. En MAIRA-2, utilizamos LLama-3-70B-Instruct
para esto, que se puede consultar como un modelo ChatOpenAI. Diferentes LLM de back-end pueden comportarse de manera diferente y producir resultados métricos diferentes. En particular, un modelo que tenga un desempeño deficiente en la verificación de vinculación no debe usarse para RadFact. Para confirmar que la verificación de vinculación se comporta como se esperaba, ejecute python src/radfact/cli/run_radfact_test_examples.py
y confirme que los resultados sean similares a los esperados. Los resultados esperados se obtuvieron utilizando el modelo LLama-3-70b-Instruct
.
Tenga en cuenta que esto no prueba el comportamiento del paso de informe de frases.
La clase LLMEngine
permite el procesamiento paralelo en múltiples puntos finales. Si tiene acceso a varios puntos finales con diferente rendimiento, el motor puede fragmentar los datos entre los puntos finales proporcionalmente a su velocidad. El motor también permite el procesamiento paralelo de solicitudes a un único punto final. Esto se utiliza de forma predeterminada independientemente del número de puntos finales. Consulte el archivo de configuración de los puntos finales para conocer las opciones speed_factor
y num_parallel_processes
. Además, el motor se encarga del procesamiento por lotes y del almacenamiento en caché intermedio de los resultados. Todos los resultados intermedios se almacenan en el directorio outputs/radfact
en una carpeta de identificación de ejecución etiquetada con la marca de tiempo inicial, por ejemplo, outputs/radfact/run_20240814_075225
. La estructura de carpetas es la siguiente:
outputs/radfact/run_20240814_075225
├── batch_outputs
│ ├── outputs_0_100.json
| ├── .
| ├── .
| ├── .
│ └── outputs_1000_1100.json
├── progress
│ ├── subset_0_240.csv
| ├── .
| ├── .
| ├── .
│ └── subset_800_1100.csv
├── skipped
│ ├── subset_0_240.csv
| ├── .
| ├── .
| ├── .
│ └── subset_800_1100.csv
├── outputs.json
├── progress.csv
└── skipped.csv
outputs.json
contiene los resultados finales de todos los puntos de datos. progress.csv
contiene el progreso del procesamiento de cada punto final. batch_outputs
contiene los resultados intermedios por tamaño de lote. skipped
contiene los puntos de datos que se omitieron debido a errores.
Puede consultar el cuaderno Getting_started para ver cómo ejecutar RadFact con sus propios datos. Recomendamos encarecidamente leer primero el cuaderno para comprender el flujo de trabajo de RadFact y cómo utilizarlo. También proporcionamos un script para ejecutar RadFact en sus datos. Asegúrese de haber configurado los puntos finales como se describe anteriormente antes de ejecutar el script. El comando run_radfact
ejecuta el script python src/radfact/cli/run_radfact.py
bajo el capó. Puede anular el comportamiento predeterminado mediante los argumentos de la línea de comando que se explican a continuación ejecutando run_radfact --help
. Debe tener el paquete instalado localmente para poder ejecutar el script.
$ run_radfact --help
usage: run_radfact [-h] [--radfact_config_name RADFACT_CONFIG_NAME] [--phrases_config_name PHRASES_CONFIG_NAME] --input_path INPUT_PATH [--is_narrative_text] [--output_dir OUTPUT_DIR] [--bootstrap_samples BOOTSTRAP_SAMPLES]
Compute RadFact metric for a set of samples and saves the results to a json file.
options:
-h, --help show this help message and exit
--input_path INPUT_PATH
The path to the csv or json file containing the samples to compute RadFact for. For finding generation samples, the csv file should have columns ' example_id ' ,
' prediction ' , and ' target ' similar to the example in ` examples/findings_generation_examples.csv ` . For grounded reporting samples, provide a json file in the
same format as ` examples/grounded_reporting_examples.json ` .
--is_narrative_text Whether the input samples are narrative text or not. If true, the input samples are expected to be narrative text, otherwise they are expected to be grounded
phrases.
--radfact_config_name RADFACT_CONFIG_NAME
The name of the config file for RadFact processing. We use the default config file but you can provide a custom config. Make sure the config follows the same
structure as ` configs/radfact.yaml ` and is saved in the ` configs ` directory. This is necessary for hydra initialization from the ` configs ` directory.
--phrases_config_name PHRASES_CONFIG_NAME
The name of the config file for reports to phrases conversion. We use the default config file but you can provide a custom config. Make sure the config follows
the same structure as ` configs/report_to_phrases.yaml ` and is saved in the ` configs ` directory. This is necessary for hydra initialization from the ` configs `
directory.
--output_dir OUTPUT_DIR
Path to the directory where the results will be saved as a json file.
--bootstrap_samples BOOTSTRAP_SAMPLES
Number of bootstrap samples to use for computing the confidence intervals. Set to 0 to disable bootstrapping.
run_radfact --input_path < path_to_input_file.csv > --is_narrative_text
run_radfact --input_path < path_to_input_file.json >
Consulte los archivos de entrada de ejemplo en el directorio examples
para conocer el formato esperado de los archivos de entrada. Los archivos de entrada deben tener el formato de un archivo CSV para informes no fundamentados hallazgos_generación_examples.csv y un archivo JSON para informes fundamentados grounded_reporting_examples.json.
El script calcula intervalos de confianza para las métricas mediante arranque. La cantidad de muestras de arranque se puede controlar utilizando el argumento --bootstrap_samples
. El valor predeterminado es 500. Para deshabilitar el arranque, configure --bootstrap_samples 0
.
num_llm_failures
. El script imprimirá el número de consultas omitidas al final de la ejecución y las almacenará en el directorio skipped
en la carpeta de identificación de ejecución. También verá un mensaje de advertencia en los registros para cada consulta fallida. WARNING: No response for example {query_id}. Setting as NOT ENTAILED
.
También proporcionamos un script para convertir informes en frases. Esto es útil cuando tiene un informe narrativo y desea convertirlo en una lista de frases para la evaluación de RadFact. Puede ejecutar este paso sin conexión y luego usar el archivo de salida como entrada para RadFact. Asegúrese de haber configurado los puntos finales como se describe anteriormente antes de ejecutar el script. El comando run_report_to_phrases
ejecuta el script python src/radfact/cli/run_report_to_phrases.py
bajo el capó.
run_report_to_phrases dataset.csv_path= < your_path_to_cxr_reports >
Este script se puede configurar mediante el archivo de configuración report_to_phrases.yaml
. Puede especificar el archivo de entrada, el archivo de salida y el punto final que se utilizará para la conversión.
Si es necesario, RadFact primero divide los informes en oraciones individuales que describen como máximo un hallazgo. Luego utiliza las capacidades de inferencia lógica de un modelo de lenguaje grande para determinar si estas oraciones están lógicamente respaldadas ("implicadas") dado el informe de referencia. Calculamos esto en dos direcciones, primero usando el informe real (original) como referencia, y viceversa, usando el informe generado por el modelo como referencia. Esto permite cuantificar tanto la exactitud como la integridad.
En general, RadFact proporciona seis medidas de calidad (fundamentada) de los informes:
Métrico | Definición | ¿Qué nos dice? | ¿Toma de tierra? |
---|---|---|---|
Precisión lógica | La fracción de oraciones generadas que implica el informe de verdad sobre el terreno. | Qué veraz es la generación modelo: penaliza a las generaciones incorrectas. | ❌ |
Recuerdo lógico | La fracción de oraciones de verdad fundamental que implica el informe generado. | Qué tan completo es el informe generado: penaliza las omisiones. | ❌ |
Precisión de puesta a tierra | La fracción de oraciones lógicamente vinculadas y fundamentadas que también están espacialmente vinculadas. | ¿Con qué frecuencia los hallazgos generados correctamente también están correctamente fundamentados? | ✔️ |
Retiro de puesta a tierra | La fracción de oraciones de verdad fundamental fundamentadas lógicamente implicadas que también están implicadas espacialmente. | ¿Con qué frecuencia los resultados captados correctamente también están correctamente fundamentados? | ✔️ |
Precisión espacial | La fracción de todas las oraciones generadas fundamentadas que están implicadas tanto lógica como espacialmente. | Una puntuación baja significa que el modelo ha generado cuadros innecesarios o cuadros para oraciones incorrectas. | ✔️ |
Recuerdo espacial | La fracción de todas las oraciones de verdad fundamental fundamentadas que están implicadas tanto lógica como espacialmente. | Una puntuación baja significa que el modelo no pudo generar cuadros para los hallazgos en la referencia, posiblemente al describir el hallazgo incorrectamente o no describirlo en absoluto. | ✔️ |
Las {precisión, recuerdo} espaciales son menos interpretables de inmediato que las otras métricas, pero las incluimos para controlar el denominador implícito en la base {precisión, recuerdo}: si solo evaluamos la calidad de las cajas de oraciones lógicamente implicadas medidas por la base {precisión, recuerdo}, no capturamos fallas de conexión a tierra que surgen de cuadros extraños asociados con oraciones incorrectas (por ejemplo, hallazgos totalmente inventados) o cuadros faltantes asociados con hallazgos omitidos.
RadFact utiliza LLM en dos pasos. En ambos casos, utilizamos alrededor de 10 ejemplos de pocas tomas.
La verificación de vinculación unidireccional (parte del paso 2) funciona de la siguiente manera:
Esto nos permite etiquetar cada oración como lógicamente implicada (o no) y espacialmente implicada (o no) y, por lo tanto, calcular las métricas de RadFact enumeradas anteriormente. Tenga en cuenta que la vinculación espacial solo se define para oraciones con cuadros.
Para la conversión de informes en oraciones individuales, generamos ejemplos sintéticos al estilo de los informes MIMIC-CXR, utilizando la sección FINDINGS
. Los informes MIMIC originales están protegidos por un acuerdo de uso de datos que prohíbe la redistribución. Dividimos manualmente los informes narrativos en oraciones individuales. Los ejemplos y el mensaje del sistema se pueden ver en llm_utils.report_to_phrases.prompts
.
Para la verificación de vinculación, los ejemplos de pocas tomas provienen de un conjunto de datos privado ("USMix"). Cada ejemplo contiene oraciones de dos informes, que seleccionamos para que sean similares pero no idénticos utilizando las estadísticas tf-idf. En colaboración con un radiólogo consultor, los etiquetamos manualmente con el estado de vinculación y la evidencia. A pesar de ser una tarea de inferencia lógica, existe un grado de subjetividad en la verificación de implicaciones, que surge de cómo se interpretan estrictamente ciertos conceptos. Por lo tanto, algunos de estos ejemplos podrían ser cuestionados. Los ejemplos y mensajes del sistema están disponibles en llm_utils.nli.prompts
.
Para citar RadFact, puede utilizar:
@article { Bannur2024MAIRA2GR ,
title = { MAIRA-2: Grounded Radiology Report Generation } ,
author = { Shruthi Bannur and Kenza Bouzid and Daniel C. Castro and Anton Schwaighofer and Sam Bond-Taylor and Maximilian Ilse and Fernando P'erez-Garc'ia and Valentina Salvatelli and Harshita Sharma and Felix Meissen and Mercy Prasanna Ranjit and Shaury Srivastav and Julia Gong and Fabian Falck and Ozan Oktay and Anja Thieme and Matthew P. Lungren and Maria T. A. Wetscherek and Javier Alvarez-Valle and Stephanie L. Hyland } ,
journal = { arXiv } ,
year = { 2024 } ,
volume = { abs/2406.04449 } ,
url = { https://arxiv.org/abs/2406.04449 }
}
RadFact se proporciona únicamente para uso en investigación. RadFact no está diseñado, previsto ni puesto a disposición para su uso en el diagnóstico, prevención, mitigación o tratamiento de una enfermedad o afección médica ni para realizar ninguna función médica, y no se ha establecido el desempeño de RadFact para dichos fines. Usted es el único responsable de cualquier uso de RadFact, incluida la incorporación a cualquier producto destinado a fines médicos.
Este proyecto agradece contribuciones y sugerencias. La mayoría de las contribuciones requieren que usted acepte un Acuerdo de licencia de colaborador (CLA) que declara que tiene derecho a otorgarnos, y de hecho lo hace, los derechos para usar su contribución. Para obtener más detalles, visite https://cla.opensource.microsoft.com.
Cuando envía una solicitud de extracción, un bot CLA determinará automáticamente si necesita proporcionar un CLA y decorar el PR de manera adecuada (por ejemplo, verificación de estado, comentario). Simplemente siga las instrucciones proporcionadas por el bot. Solo necesitarás hacer esto una vez en todos los repositorios que utilicen nuestro CLA.
Este proyecto ha adoptado el Código de conducta de código abierto de Microsoft. Para obtener más información, consulte las preguntas frecuentes sobre el Código de conducta o comuníquese con [email protected] si tiene alguna pregunta o comentario adicional.
Este proyecto puede contener marcas comerciales o logotipos de proyectos, productos o servicios. El uso autorizado de las marcas comerciales o logotipos de Microsoft está sujeto y debe seguir las Pautas de marcas y marcas comerciales de Microsoft. El uso de marcas comerciales o logotipos de Microsoft en versiones modificadas de este proyecto no debe causar confusión ni implicar patrocinio de Microsoft. Cualquier uso de marcas comerciales o logotipos de terceros está sujeto a las políticas de dichos terceros.