RadFact — это платформа для оценки отчетов о радиологических исследованиях, созданных с помощью модели, на основе достоверного отчета с обоснованием или без него . Используя возможности логического вывода больших языковых моделей, RadFact представляет собой не простое число, а набор показателей, отражающих аспекты точности и отзыва на уровне только текста и текста и обоснования.
RadFact был представлен в MAIRA-2: Создание обоснованных отчетов о радиологии. Здесь мы предоставляем реализацию метрики с открытым исходным кодом, чтобы облегчить ее использование и разработку.
LLMEngine
для параллельной обработкиЧтобы запустить RadFact, вам просто нужно клонировать этот репозиторий и выполнить следующую команду:
pip install .
При этом будет установлен пакет radfact
и все его зависимости.
В качестве альтернативы мы предоставляем Makefile
для настройки среды conda со всеми зависимостями. Вы можете создать среду с помощью:
make miniconda
make mamba
make env
conda activate radfact
На первом этапе устанавливается miniconda, на втором — mamba для быстрого разрешения зависимостей, а на третьем — создается среда conda под названием radfact
со всеми зависимостями. При этом пакет radfact также будет установлен в редактируемом режиме по умолчанию с помощью рецепта setup_packages_with_deps
(см. Makefile). Наконец, активируйте среду для запуска RadFact. Это настоятельно рекомендуется, если вы намерены внести свой вклад в проект.
Чтобы использовать RadFact, вам необходим доступ к большой языковой модели. Вам необходимо сначала настроить конечные точки с аутентификацией, а затем подтвердить, что они ведут себя должным образом, с помощью нашего тестового сценария.
LLM должен быть доступен как конечная точка API и поддерживаться langchain
(версия 0.1.4). Мы поддерживаем два типа моделей: модели AzureChatOpenAI и ChatOpenAI. Первый подходит для моделей GPT, доступных в Azure, а второй — для моделей, развернутых вручную, таких как Llama-3 в Azure.
Мы поддерживаем следующие методы аутентификации:
API_KEY
ключ API конечной точки. Мы используем API_KEY
в качестве имени переменной среды по умолчанию. Если вы используете другое имя, вы можете указать его в конфигурации конечной точки через api_key_env_var_name
. Это особенно полезно при использовании нескольких конечных точек с разными ключами API.config.json
в корневой каталог проекта. Эта конфигурация должна иметь ключи subscription_id
, resource_group
и workspace_name
. Его можно скачать из рабочей области AzureML через портал. Этот файл добавляется в .gitignore
чтобы избежать случайных коммитов. Обязательно сохраните файл в корневом каталоге проекта под именем config.json
как и ожидалось классом конечной точки.key_vault_secret_name
в конфигурации конечной точки.azure_ad_token_provider
модели AzureChatOpenAI
, позволяющий автоматическое обновление токена. Это поддерживается только для моделей AzureChatOpenAI
. Чтобы узнать больше о том, как мы интегрируем конечные точки в RadFact, обратитесь к классу LLMAPIArguments
в аргументах.py, который использует объект конечной точки класса Endpoint
в endpoint.py.
Мы используем гидру для управления конфигурациями. Конфигурации конечных точек находятся по пути: configs/endpoints
.
Это пример файла конфигурации:
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"
и type: "AZURE_CHAT_OPENAI"
в зависимости от используемой конечной точки модели. Для моделей GPT, доступных в Azure, используйте type: "AZURE_CHAT_OPENAI"
. Для пользовательских развертываемых моделей, таких как Llama-3 в Azure, используйте type: "CHAT_OPENAI"
.url
и, возможно, deployment_name
указав соответствующие значения.keyvault_secret_name
является необязательным и не требуется, если вы устанавливаете API через переменную среды. Обновите api_key_env_var_name
, если вы используете для ключа API другое имя переменной среды, чем имя по умолчанию "API_KEY"
. При использовании нескольких конечных точек укажите разные api_key_env_var_name
для каждой конечной точки.speed_factor
используется, когда доступно более одной конечной точки. Это позволяет вам указать относительную скорость конечной точки по сравнению с другими, что используется для пропорционального сегментирования данных по конечным точкам.num_parallel_processes
используется для указания количества параллельных процессов, которые будут использоваться при запросе определенной конечной точки. Все запросы обрабатываются последовательно, если только для num_parallel_processes
не установлено значение больше 1, что допускает параллельную обработку. Как указано выше, при использовании RadFact для оценки необоснованных отчетов, например, повествовательных отчетов, RadFact сначала преобразует отчеты в список фраз. На этом этапе мы используем LLM, но это не обязательно должен быть тот же LLM, который использовался для проверки следствия. Вы можете указать, какая конечная точка (следовательно, LLM) используется для каждой задачи в следующих конфигурациях в разделе « override endpoints:
:
configs/report_to_phrases.yaml
— преобразование отчета в список фраз. В MAIRA-2 мы использовали для этого GPT-4, который можно запросить как модель AzureChatOpenAI.configs/radfact.yaml
— проверка наличия. В MAIRA-2 мы использовали для этого LLama-3-70B-Instruct
, который можно запросить как модель ChatOpenAI. Различные серверные LLM могут вести себя по-разному и давать разные результаты показателей. В частности, для RadFact не следует использовать модель, которая плохо работает при проверке следствия. Чтобы убедиться, что проверка соответствия работает должным образом, запустите python src/radfact/cli/run_radfact_test_examples.py
и убедитесь, что результаты аналогичны ожидаемым. Ожидаемые результаты были получены с использованием модели LLama-3-70b-Instruct
.
Обратите внимание, что при этом не проверяется поведение этапа преобразования во фразы.
Класс LLMEngine
обеспечивает параллельную обработку на нескольких конечных точках. Если у вас есть доступ к нескольким конечным точкам с разной пропускной способностью, механизм может распределить данные по конечным точкам пропорционально их скорости. Механизм также позволяет осуществлять параллельную обработку запросов к одной конечной точке. Это используется по умолчанию независимо от количества конечных точек. Обратитесь к файлу конфигурации конечных точек для получения информации о параметрах speed_factor
и num_parallel_processes
. Кроме того, движок обеспечивает пакетную обработку и промежуточное кэширование результатов. Все промежуточные результаты сохраняются в каталоге outputs/radfact
в папке с идентификатором запуска, помеченной начальной меткой времени, например, outputs/radfact/run_20240814_075225
. Структура папок следующая:
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
содержит окончательные результаты для всех точек данных. progress.csv
содержит ход обработки для каждой конечной точки. batch_outputs
содержит промежуточные результаты для каждого размера пакета. skipped
содержит точки данных, которые были пропущены из-за ошибок.
Вы можете обратиться к блокноту Getting_started, чтобы узнать, как запустить RadFact на собственных данных. Мы настоятельно рекомендуем сначала прочитать блокнот, чтобы понять рабочий процесс RadFact и способы его использования. Мы также предоставляем сценарий для запуска RadFact на ваших данных. Перед запуском сценария убедитесь, что вы настроили конечные точки, как описано выше. Команда run_radfact
запускает скрипт python src/radfact/cli/run_radfact.py
под капотом. Вы можете переопределить поведение по умолчанию с помощью аргументов командной строки, описанных ниже, запустив run_radfact --help
. Для запуска сценария вам необходимо установить пакет локально.
$ 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 >
Обратитесь к примерам входных файлов в каталоге examples
чтобы узнать ожидаемый формат входных файлов. Входные файлы должны быть в формате CSV-файла для необоснованных отчетов Finding_generation_examples.csv и файла JSON для обоснованных отчетов grounded_reporting_examples.json.
Скрипт вычисляет доверительные интервалы для метрик с помощью начальной загрузки. Количество образцов начальной загрузки можно контролировать с помощью аргумента --bootstrap_samples
. Значение по умолчанию — 500. Чтобы отключить загрузку, установите --bootstrap_samples 0
.
num_llm_failures
. Сценарий распечатает количество пропущенных запросов в конце выполнения и сохранит их в каталоге skipped
в папке с идентификатором запуска. Вы также увидите предупреждающее сообщение в журналах для каждого неудачного запроса. WARNING: No response for example {query_id}. Setting as NOT ENTAILED
.
Мы также предоставляем скрипт для преобразования отчетов во фразы. Это полезно, если у вас есть описательный отчет и вы хотите преобразовать его в список фраз для оценки RadFact. Вы можете выполнить этот шаг в автономном режиме, а затем использовать выходной файл в качестве входных данных для RadFact. Перед запуском сценария убедитесь, что вы настроили конечные точки, как описано выше. Команда run_report_to_phrases
запускает скрипт python src/radfact/cli/run_report_to_phrases.py
под капотом.
run_report_to_phrases dataset.csv_path= < your_path_to_cxr_reports >
Этот сценарий можно настроить с помощью файла конфигурации report_to_phrases.yaml
. Вы можете указать входной файл, выходной файл и конечную точку для преобразования.
При необходимости RadFact сначала разбивает отчеты на отдельные предложения, описывающие не более одного результата. Затем он использует возможности логического вывода большой языковой модели, чтобы определить, являются ли эти предложения логически поддерживаемыми («вытекающими») с учетом справочного отчета. Мы вычисляем это в двух направлениях: сначала используя основной (исходный) отчет в качестве эталона, и наоборот, используя в качестве эталона отчет, созданный моделью. Это позволяет количественно оценить как правильность, так и полноту.
В целом, RadFact предоставляет шесть показателей (обоснованного) качества отчетов:
Метрика | Определение | Что это нам говорит? | Заземление? |
---|---|---|---|
Логическая точность | Доля сгенерированных предложений, которые влекут за собой достоверный отчет. | Насколько правдивы модели поколений: она наказывает неправильные поколения. | ❌ |
Логический отзыв | Доля достоверных предложений, которые содержатся в сгенерированном отчете. | Насколько полным является сформированный отчет: в нем предусмотрены штрафы за упущения. | ❌ |
Точность заземления | Доля логически обусловленных обоснованных предложений порождает предложения, которые также обусловлены пространственно. | Как часто правильно полученные выводы также правильно обоснованы? | ✔️ |
Отзыв о заземлении | Доля логически обоснованных истинных предложений, которые также обусловлены пространственно. | Как часто правильно зафиксированные выводы также правильно обоснованы? | ✔️ |
Пространственная точность | Доля всех обоснованных предложений, которые логически и пространственно обусловлены. | Низкий балл означает, что модель создала ненужные поля или поля для неправильных предложений. | ✔️ |
Пространственный отзыв | Доля всех обоснованных истинных предложений, которые логически и пространственно обусловлены. | Низкий балл означает, что модель не смогла создать рамки для результатов в ссылке, возможно, из-за неправильного описания результатов или их отсутствия вообще. | ✔️ |
Пространственные {точность, отзыв} менее поддаются немедленной интерпретации, чем другие показатели, но мы включаем их для контроля знаменателя, подразумеваемого в обосновании {точность, отзыв}: если мы оцениваем только качество блоков логически вытекающих предложений, измеренное путем обоснования {точность, отзыв}, мы не фиксируем сбои заземления, возникающие из-за посторонних полей, связанных с неправильными предложениями (например, полностью сфабрикованных выводов), или отсутствия полей, связанных с пропущенными выводами.
RadFact использует LLM в два этапа. В обоих случаях мы используем около 10 примеров из нескольких кадров.
Однонаправленная проверка последствий (часть шага 2) работает следующим образом:
Это позволяет нам маркировать каждое предложение как логически обусловленное (или нет) и пространственно обусловленное (или нет) и, следовательно, вычислять метрики RadFact, перечисленные выше. Обратите внимание, что пространственное следствие определяется только для предложений с рамками.
Для преобразования отчетов в отдельные предложения мы генерировали синтетические примеры в стиле отчетов MIMIC-CXR, используя раздел FINDINGS
. Исходные отчеты MIMIC защищены соглашением об использовании данных, которое запрещает повторное распространение. Мы вручную разбиваем повествовательные отчеты на отдельные предложения. Примеры и системное сообщение можно увидеть в разделе llm_utils.report_to_phrases.prompts
.
Для проверки следствия несколько примеров берутся из частного набора данных («USMix»). Каждый пример содержит предложения из двух отчетов, которые мы выбрали как похожие, но не идентичные, используя статистику tf-idf. Затем в сотрудничестве с консультантом-радиологом мы вручную пометили их статусом и доказательствами. Несмотря на то, что это задача логического вывода, при проверке следствий существует определенная степень субъективности, возникающая из-за того, насколько строго интерпретируются определенные концепции. Следовательно, некоторые из этих примеров могут быть оспорены. Примеры и системные сообщения доступны в разделе llm_utils.nli.prompts
.
Чтобы процитировать RadFact, вы можете использовать:
@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 предоставляется только для исследовательских целей. RadFact не разработан, не предназначен и не доступен для использования в диагностике, профилактике, смягчении или лечении заболевания или медицинского состояния, а также для выполнения каких-либо медицинских функций, и эффективность RadFact для таких целей не установлена. Вы несете единоличную ответственность за любое использование RadFact, включая включение в любой продукт, предназначенный для медицинских целей.
Этот проект приветствует вклад и предложения. Большинство вкладов требует от вас согласия с Лицензионным соглашением для авторов (CLA), в котором говорится, что вы имеете право и действительно предоставляете нам права на использование вашего вклада. Подробную информацию можно найти на странице https://cla.opensource.microsoft.com.
Когда вы отправляете запрос на включение, бот CLA автоматически определяет, нужно ли вам предоставить CLA, и соответствующим образом оформляет PR (например, проверку статуса, комментарий). Просто следуйте инструкциям бота. Вам нужно будет сделать это только один раз во всех репозиториях, используя наш CLA.
В этом проекте принят Кодекс поведения Microsoft с открытым исходным кодом. Для получения дополнительной информации см. Часто задаваемые вопросы о Кодексе поведения или свяжитесь с нами по адресу [email protected], если у вас возникнут дополнительные вопросы или комментарии.
Этот проект может содержать товарные знаки или логотипы проектов, продуктов или услуг. Разрешенное использование товарных знаков и логотипов Microsoft регулируется и должно соответствовать Руководству Microsoft по товарным знакам и брендам. Использование товарных знаков или логотипов Microsoft в измененных версиях этого проекта не должно вызывать путаницу или подразумевать спонсорство Microsoft. Любое использование товарных знаков или логотипов третьих лиц регулируется политикой этих третьих сторон.