Skip to content

Commit efe19a5

Browse files
authored
Merge pull request #12 from RWTH-TIME/update/use-scystream-1.5
update to scystream 1.5
2 parents a043eab + df10b98 commit efe19a5

8 files changed

Lines changed: 219 additions & 152 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ jobs:
2424

2525
- name: Run flake8
2626
uses: py-actions/flake8@v2
27+
with:
28+
args: --exclude=test
2729

2830
validate-compute-block:
2931
name: Validate Compute Block Config
@@ -38,7 +40,7 @@ jobs:
3840
- name: Intall dependencies
3941
run: |
4042
pip install -r requirements.txt
41-
43+
4244
- name: Check cbcs
4345
run: |
4446
python3 - <<'EOF'
@@ -132,7 +134,7 @@ jobs:
132134
tags: |
133135
type=ref, event=pr
134136
type=raw, value=latest, enable=${{ (github.ref == format('refs/heads/{0}', 'main')) }}
135-
137+
136138
- name: Build and push Docker image
137139
uses: docker/build-push-action@v5
138140
with:

cbc.yaml

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@ entrypoints:
3030
normalized_docs_output:
3131
config:
3232
normalized_docs_DB_TABLE: null
33-
normalized_docs_PG_HOST: null
34-
normalized_docs_PG_PASS: null
35-
normalized_docs_PG_PORT: null
36-
normalized_docs_PG_USER: null
33+
normalized_docs_DB_DSN: null
34+
normalized_docs_DB_SCHEMA: null
3735
description: Database Output, containing bib_id aswell as the normalized text
38-
type: pg_table
36+
type: database_table
37+
normalized_overwritten_file_output:
38+
config:
39+
normalized_overwritten_file_output_BUCKET_NAME: null
40+
normalized_overwritten_file_output_FILE_EXT: bib
41+
normalized_overwritten_file_output_FILE_NAME: null
42+
normalized_overwritten_file_output_FILE_PATH: null
43+
normalized_overwritten_file_output_S3_ACCESS_KEY: null
44+
normalized_overwritten_file_output_S3_HOST: null
45+
normalized_overwritten_file_output_S3_PORT: null
46+
normalized_overwritten_file_output_S3_SECRET_KEY: null
47+
description: The File Input Overwritten with the normalized output
48+
type: file
3949
preprocess_txt_file:
4050
description: Entrypoint to preprocess a .txt file
4151
envs:
@@ -63,10 +73,20 @@ entrypoints:
6373
normalized_docs_output:
6474
config:
6575
normalized_docs_DB_TABLE: null
66-
normalized_docs_PG_HOST: null
67-
normalized_docs_PG_PASS: null
68-
normalized_docs_PG_PORT: null
69-
normalized_docs_PG_USER: null
76+
normalized_docs_DB_DSN: null
77+
normalized_docs_DB_SCHEMA: null
7078
description: Database Output, containing bib_id aswell as the normalized text
71-
type: pg_table
79+
type: database_table
80+
normalized_overwritten_file_output:
81+
config:
82+
normalized_overwritten_file_output_BUCKET_NAME: null
83+
normalized_overwritten_file_output_FILE_EXT: txt
84+
normalized_overwritten_file_output_FILE_NAME: null
85+
normalized_overwritten_file_output_FILE_PATH: null
86+
normalized_overwritten_file_output_S3_ACCESS_KEY: null
87+
normalized_overwritten_file_output_S3_HOST: null
88+
normalized_overwritten_file_output_S3_PORT: null
89+
normalized_overwritten_file_output_S3_SECRET_KEY: null
90+
description: The File Input Overwritten with the normalized output
91+
type: file
7292
name: Language-Preprocessing

main.py

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1-
import hashlib
21
import logging
3-
42
import pandas as pd
5-
from preprocessing.core import Preprocessor
6-
from preprocessing.loader import BibLoader, TxtLoader
7-
from preprocessing.models import DocumentRecord, PreprocessedDocument
3+
4+
from pathlib import Path
5+
from typing import List
86
from scystream.sdk.core import entrypoint
97
from scystream.sdk.env.settings import (
108
EnvSettings,
11-
FileSettings,
129
InputSettings,
1310
OutputSettings,
14-
PostgresSettings,
11+
DatabaseSettings,
12+
FileSettings,
1513
)
1614
from scystream.sdk.file_handling.s3_manager import S3Operations
17-
from sqlalchemy import create_engine
18-
from sqlalchemy.sql import quoted_name
15+
from scystream.sdk.database_handling.database_manager import (
16+
PandasDatabaseOperations,
17+
)
18+
19+
from preprocessing.core import Preprocessor
20+
from preprocessing.loader import TxtLoader, BibLoader
21+
from preprocessing.models import DocumentRecord, PreprocessedDocument
1922

2023
logging.basicConfig(
2124
level=logging.INFO,
@@ -24,23 +27,13 @@
2427
logger = logging.getLogger(__name__)
2528

2629

27-
def _normalize_table_name(table_name: str) -> str:
28-
max_length = 63
29-
if len(table_name) <= max_length:
30-
return table_name
31-
digest = hashlib.sha1(table_name.encode("utf-8")).hexdigest()[:10]
32-
prefix_length = max_length - len(digest) - 1
33-
return f"{table_name[:prefix_length]}_{digest}"
34-
35-
36-
def _resolve_db_table(settings: PostgresSettings) -> str:
37-
normalized_name = _normalize_table_name(settings.DB_TABLE)
38-
settings.DB_TABLE = normalized_name
39-
return normalized_name
30+
class NormalizedDocsOutput(DatabaseSettings, OutputSettings):
31+
__identifier__ = "normalized_docs"
4032

4133

42-
class NormalizedDocsOutput(PostgresSettings, OutputSettings):
43-
__identifier__ = "normalized_docs"
34+
class NormalizedTXTOutput(FileSettings, OutputSettings):
35+
__identifier__ = "normalized_overwritten_file_output"
36+
FILE_EXT: str = "txt"
4437

4538

4639
class TXTFileInput(FileSettings, InputSettings):
@@ -55,6 +48,11 @@ class BIBFileInput(FileSettings, InputSettings):
5548
SELECTED_ATTRIBUTE: str = "Abstract"
5649

5750

51+
class NormalizedBIBOutput(FileSettings, OutputSettings):
52+
__identifier__ = "normalized_overwritten_file_output"
53+
FILE_EXT: str = "bib"
54+
55+
5856
class PreprocessTXT(EnvSettings):
5957
LANGUAGE: str = "en"
6058
FILTER_STOPWORDS: bool = True
@@ -67,6 +65,7 @@ class PreprocessTXT(EnvSettings):
6765

6866
txt_input: TXTFileInput
6967
normalized_docs_output: NormalizedDocsOutput
68+
normalized_overwritten_file_output: NormalizedTXTOutput
7069

7170

7271
class PreprocessBIB(EnvSettings):
@@ -81,44 +80,37 @@ class PreprocessBIB(EnvSettings):
8180

8281
bib_input: BIBFileInput
8382
normalized_docs_output: NormalizedDocsOutput
83+
normalized_overwritten_file_output: NormalizedBIBOutput
8484

8585

8686
def _write_preprocessed_docs_to_postgres(
8787
preprocessed_ouput: list[PreprocessedDocument],
88-
settings: PostgresSettings,
88+
settings: DatabaseSettings,
8989
):
90-
resolved_table_name = _resolve_db_table(settings)
9190
df = pd.DataFrame(
92-
[
93-
{
94-
"doc_id": d.doc_id,
95-
"tokens": d.tokens,
96-
}
97-
for d in preprocessed_ouput
98-
],
91+
[{"doc_id": d.doc_id, "tokens": d.tokens} for d in preprocessed_ouput]
9992
)
10093

10194
logger.info(
10295
"Writing %s processed documents to DB table '%s'…",
10396
len(df),
104-
resolved_table_name,
97+
settings.DB_TABLE,
10598
)
106-
engine = create_engine(
107-
f"postgresql+psycopg2://{settings.PG_USER}:{settings.PG_PASS}"
108-
f"@{settings.PG_HOST}:{int(settings.PG_PORT)}/",
109-
)
110-
111-
table_name = quoted_name(resolved_table_name, quote=True)
112-
df.to_sql(table_name, engine, if_exists="replace", index=False)
99+
db = PandasDatabaseOperations(settings.DB_DSN, settings.DB_SCHEMA)
100+
db.write(table=settings.DB_TABLE, data=df)
113101

114102
logger.info(
115103
"Successfully stored normalized documents into '%s'.",
116-
resolved_table_name,
104+
settings.DB_TABLE,
117105
)
118106

119107

120-
def _preprocess_and_store(documents: list[DocumentRecord], settings):
121-
"""Shared preprocessing logic for TXT and BIB."""
108+
def _preprocess_and_store(
109+
documents: List[DocumentRecord],
110+
overwrite_callback,
111+
settings,
112+
) -> List[PreprocessedDocument]:
113+
122114
logger.info(f"Starting preprocessing with {len(documents)} documents")
123115

124116
pre = Preprocessor(
@@ -134,30 +126,49 @@ def _preprocess_and_store(documents: list[DocumentRecord], settings):
134126
result = pre.generate_normalized_output()
135127

136128
_write_preprocessed_docs_to_postgres(
137-
result,
138-
settings.normalized_docs_output,
129+
result, settings.normalized_docs_output
130+
)
131+
132+
# Overwrite file using injected behavior
133+
export_path = Path(
134+
f"output.{settings.normalized_overwritten_file_output.FILE_EXT}"
135+
)
136+
overwrite_callback(result, export_path)
137+
138+
S3Operations.upload(
139+
settings.normalized_overwritten_file_output, export_path
139140
)
140141

141142
logger.info("Preprocessing completed successfully.")
143+
return result
142144

143145

144146
@entrypoint(PreprocessTXT)
145147
def preprocess_txt_file(settings):
146-
logger.info("Downloading TXT input from S3...")
148+
logger.info("Downloading TXT file...")
147149
S3Operations.download(settings.txt_input, settings.TXT_DOWNLOAD_PATH)
148150

149-
texts = TxtLoader.load(settings.TXT_DOWNLOAD_PATH)
151+
documents = TxtLoader.load(settings.TXT_DOWNLOAD_PATH)
150152

151-
_preprocess_and_store(texts, settings)
153+
_preprocess_and_store(
154+
documents=documents,
155+
overwrite_callback=TxtLoader.overwrite_with_results,
156+
settings=settings,
157+
)
152158

153159

154160
@entrypoint(PreprocessBIB)
155161
def preprocess_bib_file(settings):
156-
logger.info("Downloading BIB input from S3...")
162+
logger.info("Downloading BIB file...")
157163
S3Operations.download(settings.bib_input, settings.BIB_DOWNLOAD_PATH)
158164

159-
texts = BibLoader.load(
160-
settings.BIB_DOWNLOAD_PATH,
165+
loader = BibLoader(
166+
file_path=settings.BIB_DOWNLOAD_PATH,
161167
attribute=settings.bib_input.SELECTED_ATTRIBUTE,
162168
)
163-
_preprocess_and_store(texts, settings)
169+
170+
_preprocess_and_store(
171+
documents=loader.document_records,
172+
overwrite_callback=loader.overwrite_with_results,
173+
settings=settings,
174+
)

preprocessing/core.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
from nltk.stem.porter import PorterStemmer
66
from preprocessing.models import PreprocessedDocument, DocumentRecord
77

8-
LANG_TO_SPACY_MODELS = {
9-
"en": "en_core_web_sm",
10-
"de": "de_core_news_sm"
11-
}
8+
LANG_TO_SPACY_MODELS = {"en": "en_core_web_sm", "de": "de_core_news_sm"}
129
logger = logging.getLogger(__name__)
1310

1411

@@ -45,12 +42,11 @@ def __init__(
4542
self.documents: List[DocumentRecord] = []
4643

4744
def filter_tokens(
48-
self,
49-
tokens: list[spacy.tokens.Token],
50-
filter_stopwords: bool = False
45+
self, tokens: list[spacy.tokens.Token], filter_stopwords: bool = False
5146
) -> list[spacy.tokens.Token]:
5247
return [
53-
t for t in tokens
48+
t
49+
for t in tokens
5450
if t.is_alpha
5551
and (not filter_stopwords or not t.is_stop)
5652
and len(t.text) > 2
@@ -80,20 +76,17 @@ def generate_normalized_output(self) -> List[PreprocessedDocument]:
8076
if self.use_ngrams and self.ngram_min > 1:
8177
for n in range(self.ngram_min, self.ngram_max + 1):
8278
for i in range(len(normalized) - n + 1):
83-
ngram = " ".join(normalized[i:i+n])
79+
ngram = " ".join(normalized[i:i + n]) # fmt: off
8480
doc_terms.append(ngram)
8581

86-
processed_docs.append(PreprocessedDocument(
87-
doc_id=record.doc_id,
88-
tokens=doc_terms
89-
))
82+
processed_docs.append(
83+
PreprocessedDocument(doc_id=record.doc_id, tokens=doc_terms)
84+
)
9085

9186
return processed_docs
9287

9388
def normalize_token(
94-
self,
95-
token: spacy.tokens.Token,
96-
porter: PorterStemmer
89+
self, token: spacy.tokens.Token, porter: PorterStemmer
9790
):
9891
"""Apply lemma or stem normalization."""
9992
word = token.text.lower() if not token.text.isupper() else token.text

0 commit comments

Comments
 (0)