Skip to content

Commit

Permalink
added new integrations test and fix docker build on github AB#1035
Browse files Browse the repository at this point in the history
  • Loading branch information
borg committed Oct 17, 2024
1 parent b265de9 commit d788114
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 42 deletions.
19 changes: 10 additions & 9 deletions .github/workflows/build-and-push-docker.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build and Push Image
name: Build and Push Images

on:
release:
Expand Down Expand Up @@ -33,15 +33,16 @@ jobs:
echo "Commit SHA (short): $short_sha"
echo "short_sha=$short_sha" >> $GITHUB_ENV
- name: Build the Docker image
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:latest .
- name: Tag the Docker image with Git tag and commit hash
# Build and push the htrflow.dockerfile image with both 'latest' and Git tag + commit hash
- name: Build and push htrflow image
run: |
docker build -f docker/htrflow.dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:latest .
docker tag ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:latest ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:$latest_tag-$short_sha
- name: Push Docker images to Docker Hub
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:latest
docker push ${{ secrets.DOCKERHUB_USERNAME }}/htrflow:$latest_tag-$short_sha
# Build and push the htrflow_openmmlab.dockerfile image with Git tag and commit hash
- name: Build and push htrflow_openmmlab image
run: |
docker build -f docker/htrflow_openmmlab.dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/htrflow_openmmlab:$latest_tag-$short_sha .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/htrflow_openmmlab:$latest_tag-$short_sha
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Run tests
run: uv run pytest -m "not gpu"
run: uv run pytest -m "not gpu and not openmmlab"
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ addopts = "-v --cov htrflow --cov-report term-missing --no-cov-on-fail"
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"gpu: marks tests as gpu (deselect with '-m \"not gpu\"')",
"openmmlab: marks tests as openmmlab (deselect with '-m \"not openmmlab\"')"
]
pythonpath = "src"
testpaths = ["tests/unit", "tests/integration"]
Expand Down
30 changes: 22 additions & 8 deletions src/htrflow/models/huggingface/llava_next.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(
self,
model: str = "llava-hf/llava-v1.6-mistral-7b-hf",
processor: str = "llava-hf/llava-v1.6-mistral-7b-hf",
prompt: str = "[INST] <image>\Please transcribe the handwritten English text displayed in the image [/INST]",
prompt: str = "[INST] <image> Please transcribe the handwritten English text displayed in the image [/INST]",
device: str | None = None,
*model_args,
):
Expand All @@ -51,7 +51,9 @@ def __init__(

processor = processor or model

self.processor = LlavaNextProcessor.from_pretrained(processor, cache_dir=self.cache_dir, token=True)
self.processor = LlavaNextProcessor.from_pretrained(
processor, cache_dir=self.cache_dir, token=True
)

self.prompt = prompt

Expand All @@ -71,14 +73,20 @@ def __init__(

def _predict(self, images: list[np.ndarray], **generation_kwargs) -> list[Result]:
generation_kwargs = self._prepare_generation_kwargs(**generation_kwargs)
metadata = self.metadata | ({"generation_args": generation_kwargs} if generation_kwargs else {})
metadata = self.metadata | (
{"generation_args": generation_kwargs} if generation_kwargs else {}
)

prompts = [self.prompt] * len(images)

model_inputs = self.processor(prompts, images=images, return_tensors="pt", padding=True).to(self.model.device)
model_inputs = self.processor(
prompts, images=images, return_tensors="pt", padding=True
).to(self.model.device)
model_outputs = self.model.generate(**model_inputs, **generation_kwargs)

texts = self.processor.batch_decode(model_outputs.sequences, skip_special_tokens=True)
texts = self.processor.batch_decode(
model_outputs.sequences, skip_special_tokens=True
)

scores = model_outputs.sequences_scores.tolist()
step = generation_kwargs["num_return_sequences"]
Expand Down Expand Up @@ -147,10 +155,16 @@ def _create_text_results(
texts_chunk = texts[i : i + step]
scores_chunk = scores[i : i + step]

without_prompt_texts_chunk = [re.sub(r"\[INST\].*?\[/INST\]", "", text) for text in texts_chunk]
without_prompt_texts_chunk = [
re.sub(r"\[INST\].*?\[/INST\]", "", text) for text in texts_chunk
]

recognized_text = RecognizedText(texts=without_prompt_texts_chunk, scores=scores_chunk)
result = Result.text_recognition_result(metadata=metadata, text=recognized_text)
recognized_text = RecognizedText(
texts=without_prompt_texts_chunk, scores=scores_chunk
)
result = Result.text_recognition_result(
metadata=metadata, text=recognized_text
)
results.append(result)
return results

Expand Down
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,12 @@

steps:

- step: TextRecognition
settings:
model: Satrn
model_settings:
model: Riksarkivet/satrn_htr
generation_settings:
batch_size: 1
num_beams: 1

- step: TextRecognition
settings:
model: TrOCR
model_settings:
model: Riksarkivet/trocr-base-handwritten-hist-swe-2
generation_settings:
batch_size: 1
num_beams: 1
num_beams: 1

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# HTR pipeline

steps:

- step: TextRecognition
settings:
model: Satrn
model_settings:
model: Riksarkivet/satrn_htr
generation_settings:
batch_size: 1
num_beams: 1

52 changes: 52 additions & 0 deletions tests/integration/data/pipelines/test_gpu_svea_htr_pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# HTRFlow demo pipeline
# This pipeline works well on pages with running text

steps:

# Region segmentation
- step: Segmentation
settings:
model: yolo
model_settings:
model: Riksarkivet/yolov9-regions-1
generation_settings:
batch_size: 1
# Line segementation
- step: Segmentation
settings:
model: yolo
model_settings:
model: Riksarkivet/yolov9-lines-within-regions-1
generation_settings:
batch_size: 1
# Text recognition
- step: TextRecognition
settings:
model: WordLevelTrocr
model_settings:
model: Riksarkivet/trocr-base-handwritten-hist-swe-2
generation_settings:
batch_size: 1
num_beams: 1
# Order regions by reading order
- step: ReadingOrderMarginalia
settings:
two_page: always
# Export to Alto and Page XML
- step: Export
settings:
dest: outputs/alto
format: alto
- step: Export
settings:
dest: outputs/page
format: page

# Sets label format to regionX_lineY_wordZ
labels:
level_labels:
- region
- line
- word
sep: _
template: "{label}{number}"
3 changes: 0 additions & 3 deletions tests/integration/test_gpu_availability.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import pytest
import torch

SELECTOR_ARGO_SERVER_URL = "http://localhost:2746"
SELECTOR_SERVICE_ACCOUNT = "htrflow-service-account"


@pytest.mark.gpu
def test_gpu_availability():
Expand Down
48 changes: 39 additions & 9 deletions tests/integration/test_gpu_htr_model_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,14 @@

runner = CliRunner()

image_path = "tests/integration/data/trocr_example.png"
pipeline_path = "tests/integration/data/test_gpu_htr_model_pipeline.yaml"


@pytest.fixture(scope="module")
def check_test_files():
def run_pipeline_test(image_path, pipeline_path):
"""Helper function to run the pipeline test."""
assert os.path.exists(image_path), f"Test image not found: {image_path}"
assert os.path.exists(
pipeline_path
), f"Test pipeline YAML not found: {pipeline_path}"


@pytest.mark.gpu
def test_run_htr_pipeline(check_test_files):
result = runner.invoke(
app,
[
Expand All @@ -34,4 +28,40 @@ def test_run_htr_pipeline(check_test_files):

assert (
result.exit_code == 0
), f"Pipeline returns sucessfully exit code {result.exit_code}"
), f"Pipeline returns successfully, exit code {result.exit_code}"


@pytest.mark.gpu
@pytest.mark.parametrize(
"image_path, pipeline_path",
[
(
"tests/integration/data/images/trocr_example.png",
"tests/integration/data/pipelines/test_gpu_hf_htr_pipeline.yaml",
),
(
"tests/integration/data/images/trocr_example.png",
"tests/integration/data/pipelines/test_gpu_svea_htr_pipeline.yaml",
),
],
)
def test_run_htr_pipeline(image_path, pipeline_path):
run_pipeline_test(image_path, pipeline_path)


@pytest.mark.openmmlab
@pytest.mark.parametrize(
"image_path, pipeline_path",
[
(
"tests/integration/data/images/trocr_example.png",
"tests/integration/data/pipelines/test_gpu_hf_htr_pipeline.yaml",
),
(
"tests/integration/data/images/trocr_example.png",
"tests/integration/data/pipelines/test_gpu_opennmlab_htr_pipeline.yaml",
),
],
)
def test_run_openmmlab_pipeline(image_path, pipeline_path):
run_pipeline_test(image_path, pipeline_path)
9 changes: 7 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ deps =
pytest
lorem
pytest-cov
commands = pytest -m "not gpu"
commands = pytest -m "gpu"

[testenv:openmmlab]
usedevelop = true
description = "Run tests with OpenMMLab packages"
deps =
mmcv @ https://github.com/Swedish-National-Archives-AI-lab/openmim_install/raw/main/mmcv-2.0.0-cp310-cp310-manylinux1_x86_64.whl
Expand All @@ -18,8 +19,12 @@ deps =
mmocr==1.0.1
yapf==0.40.1

commands_pre =
uv pip show mmocr
uv pip show mmdet

commands =
uv run pytest -m gpu {posargs}
uv run pytest -m "openmmlab"

[testenv:py312]
basepython = python3.12
Expand Down

0 comments on commit d788114

Please sign in to comment.