Skip to content

Commit 40de307

Browse files
[SPARKNLP-1341] Add MultiColumnAssembler (#14743)
* Add AnnotationMerger annotator, docs, and tests * Add tests cases for readerassembler * Rename AnnotationMerger to MultiColumnAssembler --------- Co-authored-by: Devin Ha <devin@trungducha.de>
1 parent e6b9e97 commit 40de307

10 files changed

Lines changed: 1410 additions & 1 deletion

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
{%- capture title -%}
2+
MultiColumnAssembler
3+
{%- endcapture -%}
4+
5+
{%- capture description -%}
6+
Merges multiple annotation columns into a single annotation column. This is useful when
7+
multiple annotators produce separate annotation columns (e.g., `document_text`,
8+
`document_table` from [ReaderAssembler](/docs/en/annotators#readerassembler)) and a downstream
9+
annotator (e.g., [AutoGGUFVisionModel](/docs/en/annotators#autoggufvisionmodel)) expects a
10+
single input column containing all annotations.
11+
12+
Annotations from all input columns are collected and concatenated into the output column.
13+
The output annotator type defaults to `DOCUMENT` but can be configured via
14+
`setOutputAsAnnotatorType`. Each annotation's metadata is preserved, and a `source_column`
15+
key is added to track which input column the annotation originated from. All
16+
annotations from the first input column appear first, then all from the second, and so on.
17+
18+
**Note:** All input columns must use the standard `Annotation` schema. Columns that use the
19+
`AnnotationImage` schema (e.g., IMAGE-typed columns from `ReaderAssembler`) are **not
20+
supported** and will cause a validation error.
21+
22+
For more extended examples see the
23+
[Examples](https://github.com/JohnSnowLabs/spark-nlp/blob/master/examples/python/annotation/text/english/annotation-merger/Merging_Annotation_Columns.ipynb).
24+
{%- endcapture -%}
25+
26+
{%- capture input_anno -%}
27+
DOCUMENT
28+
{%- endcapture -%}
29+
30+
{%- capture output_anno -%}
31+
DOCUMENT
32+
{%- endcapture -%}
33+
34+
{%- capture python_example -%}
35+
import sparknlp
36+
from sparknlp.base import *
37+
from pyspark.ml import Pipeline
38+
39+
documentAssembler1 = DocumentAssembler() \
40+
.setInputCol("text") \
41+
.setOutputCol("document_text")
42+
43+
documentAssembler2 = DocumentAssembler() \
44+
.setInputCol("table") \
45+
.setOutputCol("document_table")
46+
47+
multiColumnAssembler = MultiColumnAssembler() \
48+
.setInputCols(["document_text", "document_table"]) \
49+
.setOutputCol("merged_document")
50+
51+
data = spark.createDataFrame(
52+
[("Hello world", "Name | Age\nJohn | 30")],
53+
["text", "table"]
54+
)
55+
56+
pipeline = Pipeline().setStages([
57+
documentAssembler1,
58+
documentAssembler2,
59+
multiColumnAssembler
60+
]).fit(data)
61+
62+
result = pipeline.transform(data)
63+
result.selectExpr("merged_document.result").show(truncate=False)
64+
+--------------------------------+
65+
|result |
66+
+--------------------------------+
67+
|[Hello world, Name | Age |
68+
|John | 30] |
69+
+--------------------------------+
70+
71+
{%- endcapture -%}
72+
73+
{%- capture scala_example -%}
74+
import spark.implicits._
75+
import com.johnsnowlabs.nlp.{MultiColumnAssembler, DocumentAssembler}
76+
import org.apache.spark.ml.Pipeline
77+
78+
val documentAssembler1 = new DocumentAssembler()
79+
.setInputCol("text")
80+
.setOutputCol("document_text")
81+
82+
val documentAssembler2 = new DocumentAssembler()
83+
.setInputCol("table")
84+
.setOutputCol("document_table")
85+
86+
val multiColumnAssembler = new MultiColumnAssembler()
87+
.setInputCols("document_text", "document_table")
88+
.setOutputCol("merged_document")
89+
90+
val data = Seq(("Hello world", "Name | Age\nJohn | 30"))
91+
.toDF("text", "table")
92+
93+
val pipeline = new Pipeline()
94+
.setStages(Array(documentAssembler1, documentAssembler2, multiColumnAssembler))
95+
.fit(data)
96+
97+
val result = pipeline.transform(data)
98+
result.selectExpr("merged_document.result").show(false)
99+
+--------------------------------+
100+
|result |
101+
+--------------------------------+
102+
|[Hello world, Name | Age |
103+
|John | 30] |
104+
+--------------------------------+
105+
106+
{%- endcapture -%}
107+
108+
{%- capture api_link -%}
109+
[MultiColumnAssembler](/api/com/johnsnowlabs/nlp/MultiColumnAssembler)
110+
{%- endcapture -%}
111+
112+
{%- capture python_api_link -%}
113+
[MultiColumnAssembler](/api/python/reference/autosummary/sparknlp/base/multi_column_assembler/index.html#sparknlp.base.multi_column_assembler.MultiColumnAssembler)
114+
{%- endcapture -%}
115+
116+
{%- capture source_link -%}
117+
[MultiColumnAssembler](https://github.com/JohnSnowLabs/spark-nlp/tree/master/src/main/scala/com/johnsnowlabs/nlp/MultiColumnAssembler.scala)
118+
{%- endcapture -%}
119+
120+
{% include templates/anno_template.md
121+
title=title
122+
description=description
123+
input_anno=input_anno
124+
output_anno=output_anno
125+
python_example=python_example
126+
scala_example=scala_example
127+
python_api_link=python_api_link
128+
api_link=api_link
129+
source_link=source_link
130+
%}
131+

docs/en/annotators.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ There are two types of Annotators:
4545
{:.table-model-big}
4646
|Annotator|Description|Version |
4747
|---|---|---|
48+
{% include templates/anno_table_entry.md path="" name="MultiColumnAssembler" summary="Merges multiple annotation columns into a single annotation column. Useful when separate document columns need to be combined for a downstream annotator."%}
4849
{% include templates/anno_table_entry.md path="" name="AutoGGUFEmbeddings" summary="Annotator that uses the llama.cpp library to generate text embeddings with large language models."%}
4950
{% include templates/anno_table_entry.md path="" name="AutoGGUFModel" summary="Annotator that uses the llama.cpp library to generate text completions with large language models."%}
5051
{% include templates/anno_table_entry.md path="" name="AutoGGUFReranker" summary="Annotator that uses the llama.cpp library to rerank text documents based on their relevance to a given query using GGUF-format reranking models."%}

0 commit comments

Comments
 (0)