mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-24 05:58:31 +00:00
Fix classification scoring (#23523)
* Add `reason` property to `TagLabel` This is to understand what score was used for selecting the entity * Build `TagLabel`s with `reason` * Increase `PIIProcessor._tolerance` This is so we correctly filter out low scores from classifiers while still maintaining the normalization that filters out confusing outcomes. e.g: an output with scores 0.3, 0.7 and 0.75, would initially filter the 0.3 and then discard the other two because they're both relatively high results. * Make database and DAO changes needed to persist `TagLabel.reason` * Update generated TypeScript types --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
0f1b2aa681
commit
dff2b394d5
@ -81,4 +81,7 @@ CREATE TABLE IF NOT EXISTS recognizer_feedback_entity (
|
||||
INDEX idx_feedback_tag (tagFQN),
|
||||
INDEX idx_feedback_status (status),
|
||||
INDEX idx_feedback_created (createdAt)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
ALTER TABLE tag_usage
|
||||
ADD COLUMN reason TEXT;
|
||||
|
||||
@ -98,4 +98,7 @@ CREATE TABLE IF NOT EXISTS recognizer_feedback_entity (
|
||||
CREATE INDEX IF NOT EXISTS idx_feedback_entity ON recognizer_feedback_entity(entityLink);
|
||||
CREATE INDEX IF NOT EXISTS idx_feedback_tag ON recognizer_feedback_entity(tagFQN);
|
||||
CREATE INDEX IF NOT EXISTS idx_feedback_status ON recognizer_feedback_entity(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_feedback_created ON recognizer_feedback_entity(createdAt);
|
||||
CREATE INDEX IF NOT EXISTS idx_feedback_created ON recognizer_feedback_entity(createdAt);
|
||||
|
||||
ALTER TABLE tag_usage
|
||||
ADD COLUMN reason TEXT;
|
||||
|
||||
@ -36,3 +36,7 @@ def get_top_classes(scores: Mapping[T, float], n: int, threshold: float) -> Sequ
|
||||
sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
|
||||
top_classes = [key for key, score in sorted_scores if score >= threshold]
|
||||
return top_classes[:n]
|
||||
|
||||
|
||||
def build_reason(tag_name: str, score: float) -> str:
|
||||
return f"Chose {tag_name} with a classification score of {score:.2f}"
|
||||
|
||||
@ -27,7 +27,11 @@ from metadata.generated.schema.type.tagLabel import (
|
||||
)
|
||||
from metadata.ingestion.ometa.ometa_api import OpenMetadata
|
||||
from metadata.pii.algorithms.tags import PIISensitivityTag
|
||||
from metadata.pii.algorithms.utils import get_top_classes, normalize_scores
|
||||
from metadata.pii.algorithms.utils import (
|
||||
build_reason,
|
||||
get_top_classes,
|
||||
normalize_scores,
|
||||
)
|
||||
from metadata.pii.base_processor import AutoClassificationProcessor
|
||||
from metadata.pii.constants import PII
|
||||
from metadata.utils import fqn
|
||||
@ -45,6 +49,7 @@ class PIIProcessor(AutoClassificationProcessor):
|
||||
self,
|
||||
config: OpenMetadataWorkflowConfig,
|
||||
metadata: OpenMetadata,
|
||||
tolerance: float = 0.7,
|
||||
):
|
||||
super().__init__(config, metadata)
|
||||
|
||||
@ -56,10 +61,10 @@ class PIIProcessor(AutoClassificationProcessor):
|
||||
self._classifier: ColumnClassifier[PIISensitivityTag] = PIISensitiveClassifier()
|
||||
|
||||
self.confidence_threshold = self.source_config.confidence / 100
|
||||
self._tolerance = 0.01
|
||||
self._tolerance = tolerance
|
||||
|
||||
@staticmethod
|
||||
def build_tag_label(tag: PIISensitivityTag) -> TagLabel:
|
||||
def build_tag_label(tag: PIISensitivityTag, score: float) -> TagLabel:
|
||||
tag_fqn = fqn.build(
|
||||
metadata=None,
|
||||
entity_type=Tag,
|
||||
@ -72,6 +77,7 @@ class PIIProcessor(AutoClassificationProcessor):
|
||||
source=TagSource.Classification,
|
||||
state=State.Suggested,
|
||||
labelType=LabelType.Generated,
|
||||
reason=build_reason(tag_fqn, score),
|
||||
)
|
||||
|
||||
return tag_label
|
||||
@ -96,5 +102,5 @@ class PIIProcessor(AutoClassificationProcessor):
|
||||
|
||||
# winner is at most 1 tag
|
||||
winner = get_top_classes(scores, 1, self.confidence_threshold)
|
||||
tag_labels = [self.build_tag_label(tag) for tag in winner]
|
||||
tag_labels = [self.build_tag_label(tag, scores[tag]) for tag in winner]
|
||||
return tag_labels
|
||||
|
||||
@ -13,6 +13,7 @@ Test Processor Class
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
from unittest import TestCase
|
||||
|
||||
from metadata.generated.schema.api.data.createDatabase import CreateDatabaseRequest
|
||||
@ -182,54 +183,6 @@ class PiiProcessorTest(TestCase):
|
||||
config=workflow_config, metadata=OpenMetadata(server_config)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
"""
|
||||
Prepare ingredients
|
||||
"""
|
||||
service = CreateDatabaseServiceRequest(
|
||||
name="test-service-table-patch",
|
||||
serviceType=DatabaseServiceType.Mysql,
|
||||
connection=DatabaseConnection(
|
||||
config=MysqlConnection(
|
||||
username="username",
|
||||
authType=BasicAuth(
|
||||
password="password",
|
||||
),
|
||||
hostPort="http://localhost:1234",
|
||||
)
|
||||
),
|
||||
)
|
||||
service_entity = cls.metadata.create_or_update(data=service)
|
||||
|
||||
create_db = CreateDatabaseRequest(
|
||||
name="test-db",
|
||||
service=service_entity.fullyQualifiedName,
|
||||
)
|
||||
|
||||
create_db_entity = cls.metadata.create_or_update(data=create_db)
|
||||
|
||||
create_schema = CreateDatabaseSchemaRequest(
|
||||
name="test-schema",
|
||||
database=create_db_entity.fullyQualifiedName,
|
||||
)
|
||||
|
||||
create_schema_entity = cls.metadata.create_or_update(data=create_schema)
|
||||
|
||||
created_table = CreateTableRequest(
|
||||
name="customers",
|
||||
columns=[
|
||||
Column(name="customer_id", dataType=DataType.INT),
|
||||
Column(name="first_name", dataType=DataType.VARCHAR, dataLength=20),
|
||||
Column(name="last_name", dataType=DataType.VARCHAR, dataLength=20),
|
||||
Column(name="first_order", dataType=DataType.DATE),
|
||||
Column(name="customer_email", dataType=DataType.VARCHAR, dataLength=20),
|
||||
Column(name="number_of_orders", dataType=DataType.BIGINT),
|
||||
],
|
||||
databaseSchema=create_schema_entity.fullyQualifiedName,
|
||||
)
|
||||
cls.table_entity = cls.metadata.create_or_update(data=created_table)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls) -> None:
|
||||
"""
|
||||
@ -310,3 +263,9 @@ class PiiProcessorTest(TestCase):
|
||||
for expected, updated in zip(EXPECTED_COLUMN_TAGS, updated_record.column_tags):
|
||||
self.assertEqual(expected.column_fqn, updated.column_fqn)
|
||||
self.assertEqual(expected.tag_label.tagFQN, updated.tag_label.tagFQN)
|
||||
self.assertRegex(
|
||||
updated.tag_label.reason,
|
||||
expected_regex=re.compile(
|
||||
f"Chose {expected.tag_label.tagFQN.root} with a classification score of \d+([.,]?\d{{1,2}})?"
|
||||
),
|
||||
)
|
||||
|
||||
@ -17,19 +17,23 @@ from metadata.pii.processor import PIIProcessor
|
||||
def test_pii_processor_build_tag_label_for_pii_sensitive():
|
||||
|
||||
tag = PIISensitivityTag.SENSITIVE
|
||||
tag_label = PIIProcessor.build_tag_label(tag)
|
||||
tag_label = PIIProcessor.build_tag_label(tag, score=0.7)
|
||||
|
||||
assert tag_label.tagFQN.root == "PII.Sensitive"
|
||||
assert tag_label.source == TagSource.Classification
|
||||
assert tag_label.state == State.Suggested
|
||||
assert tag_label.labelType == LabelType.Generated
|
||||
assert tag_label.reason == "Chose PII.Sensitive with a classification score of 0.70"
|
||||
|
||||
|
||||
def test_pii_processor_build_tag_label_for_pii_nonsensitive():
|
||||
tag = PIISensitivityTag.NONSENSITIVE
|
||||
tag_label = PIIProcessor.build_tag_label(tag)
|
||||
tag_label = PIIProcessor.build_tag_label(tag, score=0.7)
|
||||
|
||||
assert tag_label.tagFQN.root == "PII.NonSensitive"
|
||||
assert tag_label.source == TagSource.Classification
|
||||
assert tag_label.state == State.Suggested
|
||||
assert tag_label.labelType == LabelType.Generated
|
||||
assert (
|
||||
tag_label.reason == "Chose PII.NonSensitive with a classification score of 0.70"
|
||||
)
|
||||
|
||||
@ -41,9 +41,10 @@ public class CachedTagUsageDAO implements CollectionDAO.TagUsageDAO {
|
||||
String tagFQNHash,
|
||||
String targetFQNHash,
|
||||
int labelType,
|
||||
int state) {
|
||||
int state,
|
||||
String reason) {
|
||||
try {
|
||||
delegate.applyTag(source, tagFQN, tagFQNHash, targetFQNHash, labelType, state);
|
||||
delegate.applyTag(source, tagFQN, tagFQNHash, targetFQNHash, labelType, state, reason);
|
||||
if (RelationshipCache.isAvailable()) {
|
||||
invalidateTagCaches(targetFQNHash);
|
||||
RelationshipCache.bumpTag(tagFQN, 1);
|
||||
@ -437,10 +438,11 @@ public class CachedTagUsageDAO implements CollectionDAO.TagUsageDAO {
|
||||
List<String> tagFQNHashes,
|
||||
List<String> targetFQNHashes,
|
||||
List<Integer> labelTypes,
|
||||
List<Integer> states) {
|
||||
List<Integer> states,
|
||||
List<String> reasons) {
|
||||
// This is an internal method that delegates directly to the database
|
||||
delegate.applyTagsBatchInternal(
|
||||
sources, tagFQNs, tagFQNHashes, targetFQNHashes, labelTypes, states);
|
||||
sources, tagFQNs, tagFQNHashes, targetFQNHashes, labelTypes, states, reasons);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -4360,11 +4360,11 @@ public interface CollectionDAO {
|
||||
interface TagUsageDAO {
|
||||
@ConnectionAwareSqlUpdate(
|
||||
value =
|
||||
"INSERT IGNORE INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state)",
|
||||
"INSERT IGNORE INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state, reason) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state, :reason)",
|
||||
connectionType = MYSQL)
|
||||
@ConnectionAwareSqlUpdate(
|
||||
value =
|
||||
"INSERT INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state) ON CONFLICT (source, tagFQNHash, targetFQNHash) DO NOTHING",
|
||||
"INSERT INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state, reason) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state, :reason) ON CONFLICT (source, tagFQNHash, targetFQNHash) DO NOTHING",
|
||||
connectionType = POSTGRES)
|
||||
void applyTag(
|
||||
@Bind("source") int source,
|
||||
@ -4372,7 +4372,8 @@ public interface CollectionDAO {
|
||||
@BindFQN("tagFQNHash") String tagFQNHash,
|
||||
@BindFQN("targetFQNHash") String targetFQNHash,
|
||||
@Bind("labelType") int labelType,
|
||||
@Bind("state") int state);
|
||||
@Bind("state") int state,
|
||||
@Bind("reason") String reason);
|
||||
|
||||
default List<TagLabel> getTags(String targetFQN) {
|
||||
List<TagLabel> tags = getTagsInternal(targetFQN);
|
||||
@ -4404,11 +4405,11 @@ public interface CollectionDAO {
|
||||
}
|
||||
|
||||
@SqlQuery(
|
||||
"SELECT source, tagFQN, labelType, state FROM tag_usage WHERE targetFQNHash = :targetFQNHash ORDER BY tagFQN")
|
||||
"SELECT source, tagFQN, labelType, state, reason FROM tag_usage WHERE targetFQNHash = :targetFQNHash ORDER BY tagFQN")
|
||||
List<TagLabel> getTagsInternal(@BindFQN("targetFQNHash") String targetFQNHash);
|
||||
|
||||
@SqlQuery(
|
||||
"SELECT targetFQNHash, source, tagFQN, labelType, state "
|
||||
"SELECT targetFQNHash, source, tagFQN, labelType, state, reason "
|
||||
+ "FROM tag_usage "
|
||||
+ "WHERE targetFQNHash IN (<targetFQNHashes>) "
|
||||
+ "ORDER BY targetFQNHash, tagFQN")
|
||||
@ -4418,7 +4419,7 @@ public interface CollectionDAO {
|
||||
|
||||
@ConnectionAwareSqlQuery(
|
||||
value =
|
||||
"SELECT tu.source, tu.tagFQN, tu.labelType, tu.targetFQNHash, tu.state, "
|
||||
"SELECT tu.source, tu.tagFQN, tu.labelType, tu.targetFQNHash, tu.state, tu.reason, "
|
||||
+ "CASE "
|
||||
+ " WHEN tu.source = 1 THEN gterm.json "
|
||||
+ " WHEN tu.source = 0 THEN ta.json "
|
||||
@ -4430,7 +4431,7 @@ public interface CollectionDAO {
|
||||
connectionType = MYSQL)
|
||||
@ConnectionAwareSqlQuery(
|
||||
value =
|
||||
"SELECT tu.source, tu.tagFQN, tu.labelType, tu.targetFQNHash, tu.state, "
|
||||
"SELECT tu.source, tu.tagFQN, tu.labelType, tu.targetFQNHash, tu.state, tu.reason, "
|
||||
+ "CASE "
|
||||
+ " WHEN tu.source = 1 THEN gterm.json "
|
||||
+ " WHEN tu.source = 0 THEN ta.json "
|
||||
@ -4656,7 +4657,8 @@ public interface CollectionDAO {
|
||||
.withSource(TagLabel.TagSource.values()[r.getInt("source")])
|
||||
.withLabelType(TagLabel.LabelType.values()[r.getInt("labelType")])
|
||||
.withState(TagLabel.State.values()[r.getInt("state")])
|
||||
.withTagFQN(r.getString("tagFQN"));
|
||||
.withTagFQN(r.getString("tagFQN"))
|
||||
.withReason(r.getString("reason"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4677,7 +4679,8 @@ public interface CollectionDAO {
|
||||
.withSource(TagLabel.TagSource.values()[r.getInt("source")])
|
||||
.withLabelType(TagLabel.LabelType.values()[r.getInt("labelType")])
|
||||
.withState(TagLabel.State.values()[r.getInt("state")])
|
||||
.withTagFQN(r.getString("tagFQN"));
|
||||
.withTagFQN(r.getString("tagFQN"))
|
||||
.withReason(r.getString("reason"));
|
||||
TagLabel.TagSource source = TagLabel.TagSource.values()[r.getInt("source")];
|
||||
if (source == TagLabel.TagSource.CLASSIFICATION) {
|
||||
Tag tag = JsonUtils.readValue(r.getString("json"), Tag.class);
|
||||
@ -4707,6 +4710,7 @@ public interface CollectionDAO {
|
||||
tag.setTagFQN(rs.getString("tagFQN"));
|
||||
tag.setLabelType(rs.getInt("labelType"));
|
||||
tag.setState(rs.getInt("state"));
|
||||
tag.setReason(rs.getString("reason"));
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@ -4719,6 +4723,7 @@ public interface CollectionDAO {
|
||||
private String tagFQN;
|
||||
private int labelType;
|
||||
private int state;
|
||||
private String reason;
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
@ -4728,6 +4733,7 @@ public interface CollectionDAO {
|
||||
tagLabel.setTagFQN(this.tagFQN);
|
||||
tagLabel.setLabelType(TagLabel.LabelType.values()[this.labelType]);
|
||||
tagLabel.setState(TagLabel.State.values()[this.state]);
|
||||
tagLabel.setReason(this.reason);
|
||||
return tagLabel;
|
||||
}
|
||||
}
|
||||
@ -4791,6 +4797,7 @@ public interface CollectionDAO {
|
||||
List<String> targetFQNHashes = new ArrayList<>();
|
||||
List<Integer> labelTypes = new ArrayList<>();
|
||||
List<Integer> states = new ArrayList<>();
|
||||
List<String> reasons = new ArrayList<>();
|
||||
|
||||
for (TagLabel tagLabel : tagLabels) {
|
||||
sources.add(tagLabel.getSource().ordinal());
|
||||
@ -4799,19 +4806,21 @@ public interface CollectionDAO {
|
||||
targetFQNHashes.add(targetFQNHash);
|
||||
labelTypes.add(tagLabel.getLabelType().ordinal());
|
||||
states.add(tagLabel.getState().ordinal());
|
||||
reasons.add(tagLabel.getReason());
|
||||
}
|
||||
|
||||
applyTagsBatchInternal(sources, tagFQNs, tagFQNHashes, targetFQNHashes, labelTypes, states);
|
||||
applyTagsBatchInternal(
|
||||
sources, tagFQNs, tagFQNHashes, targetFQNHashes, labelTypes, states, reasons);
|
||||
}
|
||||
|
||||
@Transaction
|
||||
@ConnectionAwareSqlBatch(
|
||||
value =
|
||||
"INSERT IGNORE INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state)",
|
||||
"INSERT IGNORE INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state, reason) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state, :reason)",
|
||||
connectionType = MYSQL)
|
||||
@ConnectionAwareSqlBatch(
|
||||
value =
|
||||
"INSERT INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state) ON CONFLICT (source, tagFQNHash, targetFQNHash) DO NOTHING",
|
||||
"INSERT INTO tag_usage (source, tagFQN, tagFQNHash, targetFQNHash, labelType, state, reason) VALUES (:source, :tagFQN, :tagFQNHash, :targetFQNHash, :labelType, :state, :reason) ON CONFLICT (source, tagFQNHash, targetFQNHash) DO NOTHING",
|
||||
connectionType = POSTGRES)
|
||||
void applyTagsBatchInternal(
|
||||
@Bind("source") List<Integer> sources,
|
||||
@ -4819,7 +4828,8 @@ public interface CollectionDAO {
|
||||
@Bind("tagFQNHash") List<String> tagFQNHashes,
|
||||
@Bind("targetFQNHash") List<String> targetFQNHashes,
|
||||
@Bind("labelType") List<Integer> labelTypes,
|
||||
@Bind("state") List<Integer> states);
|
||||
@Bind("state") List<Integer> states,
|
||||
@Bind("reason") List<String> reasons);
|
||||
|
||||
/**
|
||||
* Delete multiple tags in batch to improve performance
|
||||
|
||||
@ -2465,7 +2465,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
tagLabel.getTagFQN(),
|
||||
targetFQN,
|
||||
tagLabel.getLabelType().ordinal(),
|
||||
tagLabel.getState().ordinal());
|
||||
tagLabel.getState().ordinal(),
|
||||
tagLabel.getReason());
|
||||
|
||||
// Update RDF store
|
||||
org.openmetadata.service.rdf.RdfTagUpdater.applyTag(tagLabel, targetFQN);
|
||||
|
||||
@ -202,7 +202,8 @@ class CacheWarmupIntegrationTest extends CachedOpenMetadataApplicationResourceTe
|
||||
tagHash,
|
||||
table.getFullyQualifiedName(),
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
LOG.debug("Applied tag {} to table {}", tagFQN, table.getName());
|
||||
}
|
||||
@ -423,7 +424,8 @@ class CacheWarmupIntegrationTest extends CachedOpenMetadataApplicationResourceTe
|
||||
tagHash,
|
||||
table.getFullyQualifiedName(),
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
long currentUsage = RelationshipCache.getTagUsage(testTagFQN);
|
||||
}
|
||||
|
||||
@ -216,7 +216,8 @@ class CacheWarmupServiceTest extends CachedOpenMetadataApplicationResourceTest {
|
||||
"test-tag-hash-" + i,
|
||||
entityFQN,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -249,7 +249,8 @@ public class TagUsageCacheTest extends CachedOpenMetadataApplicationResourceTest
|
||||
testTagFQNHash,
|
||||
testEntityFQNHash,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
// Verify tag usage counter was updated
|
||||
long tagUsage = RelationshipCache.getTagUsage(testTagFQN);
|
||||
@ -274,7 +275,8 @@ public class TagUsageCacheTest extends CachedOpenMetadataApplicationResourceTest
|
||||
testTagFQNHash,
|
||||
testEntityFQNHash,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
// First call should be a cache miss
|
||||
List<TagLabel> firstResult = tagUsageDAO.getTags(testEntityFQNHash);
|
||||
@ -312,7 +314,8 @@ public class TagUsageCacheTest extends CachedOpenMetadataApplicationResourceTest
|
||||
testTagFQNHash,
|
||||
testEntityFQNHash,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
// First batch call should be a cache miss
|
||||
List<CollectionDAO.TagUsageDAO.TagLabelWithFQNHash> firstBatchResult =
|
||||
@ -378,7 +381,8 @@ public class TagUsageCacheTest extends CachedOpenMetadataApplicationResourceTest
|
||||
testTagFQNHash,
|
||||
testEntityFQNHash,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
// Verify tag usage counter
|
||||
long initialUsage = RelationshipCache.getTagUsage(testTagFQN);
|
||||
@ -458,7 +462,8 @@ public class TagUsageCacheTest extends CachedOpenMetadataApplicationResourceTest
|
||||
tagHash,
|
||||
testEntityFQNHash,
|
||||
LabelType.MANUAL.ordinal(),
|
||||
State.CONFIRMED.ordinal());
|
||||
State.CONFIRMED.ordinal(),
|
||||
"Applied for testing purposes");
|
||||
|
||||
// Get tags and verify they exist
|
||||
List<TagLabel> tags = tagUsageDAO.getTags(testEntityFQNHash);
|
||||
|
||||
@ -77,17 +77,7 @@ import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -5533,4 +5523,69 @@ public class TableResourceTest extends EntityResourceTest<Table, CreateTable> {
|
||||
dataProductTest.deleteEntity(dataProduct.getId(), false, true, ADMIN_AUTH_HEADERS);
|
||||
domainTest.deleteEntity(domain.getId(), false, true, ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_columnWithMultipleTags_withClassificationReason(TestInfo test) throws IOException {
|
||||
// Patch a table:
|
||||
// 1. PII.Sensitive - from classification with reason "Classified with score 1.0"
|
||||
// 2. Personal.Name - manual tag with no reason (null)
|
||||
Column column = getColumn(C1, ColumnDataType.STRING, null);
|
||||
|
||||
CreateTable request = createRequest(test).withColumns(List.of(column));
|
||||
Table table = createEntity(request, ADMIN_AUTH_HEADERS);
|
||||
|
||||
TagLabel personalTagLabel = PERSONAL_DATA_TAG_LABEL;
|
||||
TagLabel sensitiveTagLabel =
|
||||
PII_SENSITIVE_TAG_LABEL.withReason("Classified with score 1.0"); // Classification reason
|
||||
|
||||
// Create a column with sensitive tag
|
||||
Column columnWithAutoClassification = column.withTags(List.of(sensitiveTagLabel));
|
||||
|
||||
String originalTable = JsonUtils.pojoToJson(table);
|
||||
|
||||
table = table.withColumns(List.of(columnWithAutoClassification));
|
||||
|
||||
Table patchedTable = patchEntity(table.getId(), originalTable, table, ADMIN_AUTH_HEADERS);
|
||||
|
||||
assertNotNull(patchedTable.getColumns());
|
||||
assertEquals(1, patchedTable.getColumns().size());
|
||||
Column patchedColumn = patchedTable.getColumns().getFirst();
|
||||
List<TagLabel> tags = patchedColumn.getTags();
|
||||
assertNotNull(tags);
|
||||
assertEquals(1, tags.size());
|
||||
|
||||
TagLabel piiTag = tags.getFirst();
|
||||
assertNotNull(piiTag);
|
||||
assertEquals("Sensitive", piiTag.getName());
|
||||
assertEquals("PII.Sensitive", piiTag.getTagFQN());
|
||||
assertEquals("Classified with score 1.0", piiTag.getReason());
|
||||
|
||||
// Now add personal tag manually
|
||||
Column columnWithBothTags = column.withTags(List.of(sensitiveTagLabel, personalTagLabel));
|
||||
|
||||
originalTable = JsonUtils.pojoToJson(patchedTable);
|
||||
|
||||
table = patchedTable.withColumns(List.of(columnWithBothTags));
|
||||
|
||||
patchedTable = patchEntity(table.getId(), originalTable, table, ADMIN_AUTH_HEADERS);
|
||||
|
||||
assertNotNull(patchedTable.getColumns());
|
||||
assertEquals(1, patchedTable.getColumns().size());
|
||||
patchedColumn = patchedTable.getColumns().getFirst();
|
||||
tags = patchedColumn.getTags();
|
||||
assertNotNull(tags);
|
||||
assertEquals(2, tags.size());
|
||||
|
||||
piiTag = tags.getFirst();
|
||||
assertNotNull(piiTag);
|
||||
assertEquals("Sensitive", piiTag.getName());
|
||||
assertEquals("PII.Sensitive", piiTag.getTagFQN());
|
||||
assertEquals("Classified with score 1.0", piiTag.getReason());
|
||||
|
||||
TagLabel personalTag = tags.getLast();
|
||||
assertNotNull(personalTag);
|
||||
assertEquals("Personal", personalTag.getName());
|
||||
assertEquals("PersonalData.Personal", personalTag.getTagFQN());
|
||||
assertNull(personalTag.getReason());
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,10 @@
|
||||
"href": {
|
||||
"description": "Link to the tag resource.",
|
||||
"$ref": "basic.json#/definitions/href"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "An explanation of why this tag was proposed, specially for autoclassification tags"
|
||||
}
|
||||
},
|
||||
"required": ["tagFQN", "source", "labelType", "state"],
|
||||
|
||||
@ -4331,6 +4331,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -199,6 +199,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -309,6 +309,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -222,6 +222,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -592,6 +592,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -216,6 +216,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -558,6 +558,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -574,6 +574,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -205,6 +205,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -199,6 +199,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -236,6 +236,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -257,6 +257,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -151,6 +151,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -195,6 +195,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -217,6 +217,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -304,6 +304,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -229,6 +229,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -174,6 +174,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -184,6 +184,10 @@ export interface FieldTag {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -382,6 +386,10 @@ export interface CreateSearchIndexTag {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -238,6 +238,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -237,6 +237,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -571,6 +571,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -320,6 +320,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -572,6 +572,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -159,6 +159,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -86,6 +86,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -160,6 +160,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -167,6 +167,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -58,6 +58,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -612,6 +612,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -207,6 +207,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -1311,6 +1311,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -2189,6 +2189,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -376,6 +376,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -368,6 +368,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -889,6 +889,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -391,6 +391,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -1148,6 +1148,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -352,6 +352,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -189,6 +189,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -415,6 +415,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -1317,6 +1317,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -1431,6 +1435,10 @@ export interface TierElement {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -155,6 +155,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -143,6 +143,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -52,6 +52,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -695,6 +695,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -809,6 +813,10 @@ export interface TierElement {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -62,6 +62,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -62,6 +62,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -101,6 +101,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -59,6 +59,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -133,6 +133,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -77,6 +77,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -74,6 +74,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -74,6 +74,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -383,6 +383,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -497,6 +501,10 @@ export interface TierElement {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -666,6 +666,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -780,6 +784,10 @@ export interface TagElement {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -627,6 +627,10 @@ export interface TagLabel {
|
||||
* Name of the entity instance.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
@ -741,6 +745,10 @@ export interface TagElement {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -4616,6 +4616,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -225,6 +225,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -242,6 +242,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -172,6 +172,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -204,6 +204,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -182,6 +182,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -173,6 +173,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -750,6 +750,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -190,6 +190,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -186,6 +186,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -195,6 +195,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -219,6 +219,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -293,6 +293,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -356,6 +356,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -168,6 +168,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -196,6 +196,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -197,6 +197,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -303,6 +303,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -176,6 +176,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -208,6 +208,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -187,6 +187,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -244,6 +244,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -203,6 +203,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -198,6 +198,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -428,6 +428,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -276,6 +276,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -146,6 +146,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -52,6 +52,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
@ -327,6 +327,10 @@ export interface TagLabel {
|
||||
* Name of the tag or glossary term.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* An explanation of why this tag was proposed, specially for autoclassification tags
|
||||
*/
|
||||
reason?: string;
|
||||
/**
|
||||
* Label is from Tags or Glossary.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user