Skip to content

757 add exaone path 2.0 #759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

cjs6211
Copy link

@cjs6211 cjs6211 commented Jul 10, 2025

Fixes #757 .

Description

This PR adds the latest version of the EXAONE Path model, EXAONE Path 2.0.
The model is based on Hugging Face and is hosted at: https://huggingface.co/LGAI-EXAONE/EXAONE-Path-2.0.

Status

Ready

Please ensure all the checkboxes:

  • Codeformat tests passed locally by running ./runtests.sh --codeformat.
  • In-line docstrings updated.
  • Update version and changelog in metadata.json if changing an existing bundle.
  • Please ensure the naming rules in config files meet our requirements (please refer to: CONTRIBUTING.md).
  • Ensure versions of packages such as monai, pytorch and numpy are correct in metadata.json.
  • Descriptions should be consistent with the content, such as eval_metrics of the provided weights and TorchScript modules.
  • Files larger than 25MB are excluded and replaced by providing download links in large_file.yml.
  • Avoid using path that contains personal information within config files (such as use /home/your_name/ for "bundle_root").

cjs6211 and others added 3 commits July 10, 2025 16:47
Add EXAONE Path 2.0

Signed-off-by: Jongseong Jang <[email protected]>
Signed-off-by: Jongseong Jang <[email protected]>
@ericspod ericspod requested review from Copilot and aylward July 23, 2025 16:02
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds the latest version of the EXAONE Path model (EXAONE Path 2.0) to the Hugging Face models directory. The model is a pathology foundation model with 144 million parameters designed for whole-slide image (WSI) analysis and biomarker prediction.

  • Adds complete EXAONE Path 2.0 model implementation with three-stage Vision Transformer architecture
  • Includes comprehensive utilities for WSI processing, tissue segmentation, and tensor operations
  • Provides sample data, documentation, and licensing for the new pathology model

Reviewed Changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
hf_models/README.md Updates model listing table to include EXAONE Path 2.0 entry
hf_models/EXAONE-Path-2.0/exaonepath.py Main model implementation with three-stage inference pipeline
hf_models/EXAONE-Path-2.0/networks/vit.py Vision Transformer architectures for the three processing stages
hf_models/EXAONE-Path-2.0/utils/wsi_utils.py Utilities for whole-slide image processing and tissue segmentation
hf_models/EXAONE-Path-2.0/utils/tensor_utils.py Tensor manipulation utilities for multi-stage processing
hf_models/EXAONE-Path-2.0/requirements.txt Dependencies specification including CUDA-enabled PyTorch
hf_models/EXAONE-Path-2.0/config.json Model configuration parameters
hf_models/EXAONE-Path-2.0/README.md Comprehensive documentation and usage instructions
hf_models/EXAONE-Path-2.0/LICENSE Custom license agreement for the model
hf_models/EXAONE-Path-2.0/pytorch_model.bin Pre-trained model weights (LFS tracked)
hf_models/EXAONE-Path-2.0/samples/sample.svs Sample whole-slide image file (LFS tracked)
Comments suppressed due to low confidence (2)

import typing as t
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from tracemalloc import start
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import 'start' from tracemalloc is not used anywhere in the code. This appears to be an unused import that should be removed.

Suggested change
from tracemalloc import start
# Line removed as it is unused

Copilot uses AI. Check for mistakes.


try:
from skimage import img_as_ubyte # type: ignore
except:
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except clause should specify the exception type. Consider using 'except ImportError:' to catch only the specific import error.

Suggested change
except:
except ImportError:

Copilot uses AI. Check for mistakes.

boxes = [cv2.boundingRect(c) for c in large_contours]

return (
[cv2.boundingRect(c) for c in large_contours]
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list comprehension duplicates the same computation from line 198. Consider storing the result in the 'boxes' variable and reusing it.

Suggested change
[cv2.boundingRect(c) for c in large_contours]
boxes

Copilot uses AI. Check for mistakes.

255,
dtype=wsi_arr.dtype,
)
mask_out = np.zeros((packed_size[1], packed_size[0]), dtype=np.bool)
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using deprecated 'np.bool' dtype. Should use 'np.bool_' or 'bool' instead as np.bool has been deprecated.

Suggested change
mask_out = np.zeros((packed_size[1], packed_size[0]), dtype=np.bool)
mask_out = np.zeros((packed_size[1], packed_size[0]), dtype=bool)

Copilot uses AI. Check for mistakes.

Comment on lines +272 to +274
mask_out[pos[1] : pos[1] + box[3], pos[0] : pos[0] + box[2]] = mask[
box[1] : box[1] + box[3], box[0] : box[0] + box[2]
]
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This array slicing operation spans multiple lines in a confusing way. Consider restructuring for better readability.

Suggested change
mask_out[pos[1] : pos[1] + box[3], pos[0] : pos[0] + box[2]] = mask[
box[1] : box[1] + box[3], box[0] : box[0] + box[2]
]
mask_out[
pos[1] : pos[1] + box[3], pos[0] : pos[0] + box[2]
] = mask[box[1] : box[1] + box[3], box[0] : box[0] + box[2]]

Copilot uses AI. Check for mistakes.

Comment on lines +363 to +375
white = [255, 255, 255] # 흰색 (B, G, R)

# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)

# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)

# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)

# 두께 30픽셀의 오른쪽 흰색 띠 그리기
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is in Korean. Consider translating to English for consistency in an international codebase.

Suggested change
white = [255, 255, 255] # 흰색 (B, G, R)
# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# 두께 30픽셀의 오른쪽 흰색 띠 그리기
white = [255, 255, 255] # White color (B, G, R)
# Add white bands using the cv2.copyMakeBorder function
# Draw a white band of 30-pixel thickness at the top
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# Draw a white band of 30-pixel thickness at the bottom
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# Draw a white band of 30-pixel thickness on the left
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# Draw a white band of 30-pixel thickness on the right

Copilot uses AI. Check for mistakes.

Comment on lines +363 to +375
white = [255, 255, 255] # 흰색 (B, G, R)

# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)

# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)

# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)

# 두께 30픽셀의 오른쪽 흰색 띠 그리기
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is in Korean. Consider translating to English for consistency in an international codebase.

Suggested change
white = [255, 255, 255] # 흰색 (B, G, R)
# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# 두께 30픽셀의 오른쪽 흰색 띠 그리기
white = [255, 255, 255] # White color (B, G, R)
# Add white bands using the cv2.copyMakeBorder function
# Draw a white band of 30-pixel thickness at the top
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# Draw a white band of 30-pixel thickness at the bottom
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# Draw a white band of 30-pixel thickness on the left
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# Draw a white band of 30-pixel thickness on the right

Copilot uses AI. Check for mistakes.

Comment on lines +363 to +375
white = [255, 255, 255] # 흰색 (B, G, R)

# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)

# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)

# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)

# 두께 30픽셀의 오른쪽 흰색 띠 그리기
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is in Korean. Consider translating to English for consistency in an international codebase.

Suggested change
white = [255, 255, 255] # 흰색 (B, G, R)
# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# 두께 30픽셀의 오른쪽 흰색 띠 그리기
white = [255, 255, 255] # White color (B, G, R)
# Add white bands using the cv2.copyMakeBorder function
# Draw a white band of 30-pixel thickness at the top
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# Draw a white band of 30-pixel thickness at the bottom
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# Draw a white band of 30-pixel thickness on the left
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# Draw a white band of 30-pixel thickness on the right

Copilot uses AI. Check for mistakes.

Comment on lines +363 to +375
white = [255, 255, 255] # 흰색 (B, G, R)

# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)

# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)

# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)

# 두께 30픽셀의 오른쪽 흰색 띠 그리기
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is in Korean. Consider translating to English for consistency in an international codebase.

Suggested change
white = [255, 255, 255] # 흰색 (B, G, R)
# cv2.copyMakeBorder 함수를 사용해 흰색 띠를 추가
# 두께 30픽셀의 위쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# 두께 30픽셀의 아래쪽 흰색 띠 그리기
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# 두께 30픽셀의 왼쪽 흰색 띠 그리기
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# 두께 30픽셀의 오른쪽 흰색 띠 그리기
white = [255, 255, 255] # White color (B, G, R)
# Add white bands using the cv2.copyMakeBorder function
# Draw a white band at the top with a thickness of 30 pixels
cv2.rectangle(img, (0, 0), (width, thickness), white, -1)
# Draw a white band at the bottom with a thickness of 30 pixels
cv2.rectangle(img, (0, height - thickness), (width, height), white, -1)
# Draw a white band on the left with a thickness of 30 pixels
cv2.rectangle(img, (0, 0), (thickness, height), white, -1)
# Draw a white band on the right with a thickness of 30 pixels

Copilot uses AI. Check for mistakes.

if i < len(hole_contours) and hole_contours[i]:
for hole in hole_contours[i]: # type: ignore
cv2.fillPoly(mask, [hole], 0) # type: ignore
mask = mask.astype(np.bool)
Copy link
Preview

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using deprecated 'np.bool' dtype. Should use 'np.bool_' or 'bool' instead as np.bool has been deprecated.

Suggested change
mask = mask.astype(np.bool)
mask = mask.astype(bool)

Copilot uses AI. Check for mistakes.

@ericspod
Copy link
Member

Hi @cjs6211 thank you for the contribution. We do require that models in our zoo use the bundle format. You have a lot of your own code here so I wouldn't suggest reformatting everything to use MONAI components, but there does need to be at least an inference config file which can call into code you have defined. This bundle here is an example of an inference script with few components, and just calls into a defined method to implement an inference process. You can follow that pattern here but please do look at other bundles and see what you can do to make your code into a bundle.

We do also require that this model be in the models directory and not hf_models which contains information on those models hosted on Huggingface. We already reference a EXAONEPath model hosted on hf in hf_models, if this is a later version of the same model perhaps it should be hosted in hf instead of here and we add a reference in hf_models in a similar pattern.

@aylward could you please double check that this model's license is acceptable to us, I think it's fine from our previous discussions on licenses.

Thanks!

@cjs6211
Copy link
Author

cjs6211 commented Jul 27, 2025

Hi @cjs6211 thank you for the contribution. We do require that models in our zoo use the bundle format. You have a lot of your own code here so I wouldn't suggest reformatting everything to use MONAI components, but there does need to be at least an inference config file which can call into code you have defined. This bundle here is an example of an inference script with few components, and just calls into a defined method to implement an inference process. You can follow that pattern here but please do look at other bundles and see what you can do to make your code into a bundle.

We do also require that this model be in the models directory and not hf_models which contains information on those models hosted on Huggingface. We already reference a EXAONEPath model hosted on hf in hf_models, if this is a later version of the same model perhaps it should be hosted in hf instead of here and we add a reference in hf_models in a similar pattern.

@aylward could you please double check that this model's license is acceptable to us, I think it's fine from our previous discussions on licenses.

Thanks!

Hi, @ericspod.
Regarding the comment "We already reference a EXAONEPath model hosted on hf in hf_models, if this is a later version of the same model perhaps it should be hosted in hf instead of here and we add a reference in hf_models in a similar pattern", this actually aligns well with our original intention.

We have already uploaded the EXAONE Path 2.0 model to Hugging Face at https://huggingface.co/LGAI-EXAONE/EXAONE-Path-2.0 (different from the past model), and we would like this version to be referenced in hf_models following the same pattern as the existing EXAONE Path model.

However, since we were unsure of the correct process to request this kind of update, we submitted the current pull request. Please let us know exact way to refer to EXAONE Path 2.0.

Thank you again!

@ericspod
Copy link
Member

ericspod commented Aug 5, 2025

Hi @cjs6211 thank you for the contribution. We do require that models in our zoo use the bundle format. You have a lot of your own code here so I wouldn't suggest reformatting everything to use MONAI components, but there does need to be at least an inference config file which can call into code you have defined. This bundle here is an example of an inference script with few components, and just calls into a defined method to implement an inference process. You can follow that pattern here but please do look at other bundles and see what you can do to make your code into a bundle.
We do also require that this model be in the models directory and not hf_models which contains information on those models hosted on Huggingface. We already reference a EXAONEPath model hosted on hf in hf_models, if this is a later version of the same model perhaps it should be hosted in hf instead of here and we add a reference in hf_models in a similar pattern.
@aylward could you please double check that this model's license is acceptable to us, I think it's fine from our previous discussions on licenses.
Thanks!

Hi, @ericspod. Regarding the comment "We already reference a EXAONEPath model hosted on hf in hf_models, if this is a later version of the same model perhaps it should be hosted in hf instead of here and we add a reference in hf_models in a similar pattern", this actually aligns well with our original intention.

We have already uploaded the EXAONE Path 2.0 model to Hugging Face at https://huggingface.co/LGAI-EXAONE/EXAONE-Path-2.0 (different from the past model), and we would like this version to be referenced in hf_models following the same pattern as the existing EXAONE Path model.

However, since we were unsure of the correct process to request this kind of update, we submitted the current pull request. Please let us know exact way to refer to EXAONE Path 2.0.

Thank you again!

Hi @cjs6211 I would suggest removing the files that you've proposed here and instead create a directory in hf_models with the contents similar to the existing model. You will want to replace the contents of the README.md and metadata.json files to match what your new model has but otherwise follow this as a template. The "model" link should point to the Huggingface link instead of the Github page however. I think that will work for what we want to host here and we can review again once that's done. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add EXAONE Path 2.0
2 participants