diff --git a/redaction-service-v1/redaction-service-api-v1/build.gradle.kts b/redaction-service-v1/redaction-service-api-v1/build.gradle.kts index ba585434..abc085cd 100644 --- a/redaction-service-v1/redaction-service-api-v1/build.gradle.kts +++ b/redaction-service-v1/redaction-service-api-v1/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } description = "redaction-service-api-v1" -val persistenceServiceVersion = "2.530.0" +val persistenceServiceVersion = "2.531.0" dependencies { implementation("org.springframework:spring-web:6.0.12") diff --git a/redaction-service-v1/redaction-service-server-v1/build.gradle.kts b/redaction-service-v1/redaction-service-server-v1/build.gradle.kts index 6de0cff3..595817c6 100644 --- a/redaction-service-v1/redaction-service-server-v1/build.gradle.kts +++ b/redaction-service-v1/redaction-service-server-v1/build.gradle.kts @@ -16,7 +16,7 @@ val layoutParserVersion = "0.141.0" val jacksonVersion = "2.15.2" val droolsVersion = "9.44.0.Final" val pdfBoxVersion = "3.0.0" -val persistenceServiceVersion = "2.530.0" +val persistenceServiceVersion = "2.531.0" val springBootStarterVersion = "3.1.5" val springCloudVersion = "4.0.4" val testContainersVersion = "1.19.7" diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/RedactionServiceSettings.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/RedactionServiceSettings.java index 46cdf0df..34081d3f 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/RedactionServiceSettings.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/RedactionServiceSettings.java @@ -22,6 +22,8 @@ public class RedactionServiceSettings { private boolean nerServiceEnabled = true; + private boolean azureNerServiceEnabled; + private boolean priorityMode; private long dictionaryCacheMaximumSize = 100; diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/client/model/EntityRecognitionEntity.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/client/model/EntityRecognitionEntity.java index 05009f30..282b6c64 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/client/model/EntityRecognitionEntity.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/client/model/EntityRecognitionEntity.java @@ -15,5 +15,6 @@ public class EntityRecognitionEntity { private int startOffset; private int endOffset; private String type; + private Double confidence; } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/logger/RulesLogger.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/logger/RulesLogger.java index 306e951e..37304f3e 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/logger/RulesLogger.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/logger/RulesLogger.java @@ -11,19 +11,15 @@ import lombok.RequiredArgsConstructor; * This class provides logging functionality specifically for rules execution * in a Drools context. It is designed to log messages with different log levels * (INFO, WARN, ERROR) and formats messages using a placeholder-based approach - * similar to popular logging frameworks like SLF4J. + * similar to popular logging frameworks like SLF4J.

* - *

* Log messages can include placeholders (i.e., `{}`), which will be replaced by - * the corresponding arguments when the message is formatted. - *

- *

+ * the corresponding arguments when the message is formatted.

* * Example usage: *

  *     logger.info("Message with placeholder {}", object);
  * 
- *

*/ @RequiredArgsConstructor public class RulesLogger { diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/model/NerEntities.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/model/NerEntities.java index 57542164..207c2afc 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/model/NerEntities.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/model/NerEntities.java @@ -1,5 +1,6 @@ package com.iqser.red.service.redaction.v1.server.model; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.stream.Stream; @@ -9,6 +10,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; /** @@ -17,7 +19,7 @@ import lombok.experimental.FieldDefaults; */ @Getter @AllArgsConstructor -@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +@FieldDefaults(level = AccessLevel.PRIVATE) public class NerEntities { List nerEntityList; @@ -29,6 +31,14 @@ public class NerEntities { } + public void merge(NerEntities other) { + + List mergedList = new ArrayList<>(nerEntityList); + mergedList.addAll(other.getNerEntityList()); + nerEntityList = mergedList; + } + + /** * Checks if there are any entities of a specified type. * @@ -55,11 +65,16 @@ public class NerEntities { } + + /** * Represents a single NER entity with its value, text range, and type. */ - public record NerEntity(String value, TextRange textRange, String type) { + public record NerEntity(String value, TextRange textRange, String type, Double confidence) { + public NerEntity(String value, TextRange textRange, String type) { + this(value, textRange, type, null); + } } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalysisPreparationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalysisPreparationService.java index a2b255c4..04b89554 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalysisPreparationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/AnalysisPreparationService.java @@ -336,6 +336,11 @@ public class AnalysisPreparationService { } else { nerEntities = new NerEntities(Collections.emptyList()); } + if (redactionServiceSettings.isAzureNerServiceEnabled()) { + NerEntitiesModel azureNerEntitiesModel = redactionStorageService.getAzureNerEntities(analyzeRequest.getDossierId(), analyzeRequest.getFileId()); + NerEntities azureNerEntities = NerEntitiesAdapter.toNerEntities(azureNerEntitiesModel, document); + nerEntities.merge(azureNerEntities); + } return nerEntities; } @@ -391,6 +396,12 @@ public class AnalysisPreparationService { } else { nerEntities = new NerEntities(Collections.emptyList()); } + if (redactionServiceSettings.isAzureNerServiceEnabled()) { + NerEntitiesModel azureNerEntitiesModel = redactionStorageService.getAzureNerEntities(analyzeRequest.getDossierId(), analyzeRequest.getFileId()); + azureNerEntitiesModel = filterNerEntitiesModelBySectionIds(sectionsToReanalyseIds, azureNerEntitiesModel); + NerEntities azureNerEntities = NerEntitiesAdapter.toNerEntities(azureNerEntitiesModel, document); + nerEntities.merge(azureNerEntities); + } return nerEntities; } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/EntityCreationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/EntityCreationService.java index fdc28329..cf7933f2 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/EntityCreationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/EntityCreationService.java @@ -628,7 +628,9 @@ public class EntityCreationService { .map(bBox -> Pair.of(bBox.getMaxY(), bBox.getMinY())) .map(maxMinPair -> tableNode.streamRow(tableCell.getRow()) .filter(nextTableCell -> nextTableCell.getCol() > tableCell.getCol()) - .map(nextTableCell -> RedactionSearchUtility.findTextRangesOfAllLinesWithCloseYCoordinates(maxMinPair.getLeft(), maxMinPair.getRight(), nextTableCell.getTextBlock())) + .map(nextTableCell -> RedactionSearchUtility.findTextRangesOfAllLinesWithCloseYCoordinates(maxMinPair.getLeft(), + maxMinPair.getRight(), + nextTableCell.getTextBlock())) .map(b -> b.trim(tableNode.getTextBlock())) .filter(boundary -> isValidEntityTextRange(tableNode.getTextBlock(), boundary)) .map(boundary -> byTextRange(boundary, type, entityType, tableNode)) @@ -1223,6 +1225,49 @@ public class EntityCreationService { } + /** + * Optionally creates a text entity based on a Named Entity Recognition (NER) entity + * if the confidence of the entity lies above the given minimal confidence. + * + * @param nerEntity The NER entity used for creating the text entity. + * @param minConfidence The minimal confidence required + * @param entityType The entity's classification. + * @param semanticNode The semantic node related to the NER entity. + * @return An {@link Optional} containing the new {@link TextEntity} based on the NER entity, or {@link Optional#empty()} if not created. + */ + public Optional optionalByNerEntityWithConfidence(NerEntities.NerEntity nerEntity, Double minConfidence, EntityType entityType, SemanticNode semanticNode) { + + if (nerEntity.confidence() != null && nerEntity.confidence() < minConfidence) { + return Optional.empty(); + } + return byTextRangeWithEngine(nerEntity.textRange(), nerEntity.type(), entityType, semanticNode, Set.of(Engine.NER)); + } + + + /** + * Optionally creates a text entity based on a Named Entity Recognition (NER) entity, with a specified type + * if the confidence of the entity lies above the given minimal confidence. + * + * @param nerEntity The NER entity used for creating the text entity. + * @param minConfidence The minimal confidence required + * @param type Type of the entity. + * @param entityType The entity's classification. + * @param semanticNode The semantic node related to the NER entity. + * @return An {@link Optional} containing the new {@link TextEntity} based on the NER entity, or {@link Optional#empty()} if not created. + */ + public Optional optionalByNerEntityWithConfidence(NerEntities.NerEntity nerEntity, + Double minConfidence, + String type, + EntityType entityType, + SemanticNode semanticNode) { + + if (nerEntity.confidence() != null && nerEntity.confidence() < minConfidence) { + return Optional.empty(); + } + return byTextRangeWithEngine(nerEntity.textRange(), type, entityType, semanticNode, Set.of(Engine.NER)); + } + + /** * Combines multiple NER entities into a single text entity. * @@ -1241,6 +1286,137 @@ public class EntityCreationService { } + /** + * Combines multiple NER entities into a single text entity based on the specified types and minimum parts to combine. + * + * @param nerEntities The collection of NER entities to combine. + * @param type The type for the combined entity. + * @param entityType The classification for the combined entity. + * @param semanticNode The semantic node related to these entities. + * @param essentialTypes A set of essential types that must be present in the combination. + * @param typesToCombine A set of types that should be considered for combination. + * @param minPartsToCombine The minimum number of parts that must be combined. + * @return A stream of combined {@link TextEntity} objects that match the specified criteria. + */ + public Stream combineNerEntities(NerEntities nerEntities, + String type, + EntityType entityType, + SemanticNode semanticNode, + Set essentialTypes, + Set typesToCombine, + int minPartsToCombine) { + + return NerEntitiesAdapter.combineNerEntitiesOfAllGivenTypes(nerEntities, essentialTypes, typesToCombine, minPartsToCombine) + .map(boundary -> byTextRangeWithEngine(boundary, type, entityType, semanticNode, Set.of(Engine.NER))) + .filter(Optional::isPresent) + .map(Optional::get); + } + + + /** + * Combines multiple NER entities into a single text entity based on the specified types, maximum distance between parts, and minimum parts to combine. + * + * @param nerEntities The collection of NER entities to combine. + * @param type The type for the combined entity. + * @param entityType The classification for the combined entity. + * @param semanticNode The semantic node related to these entities. + * @param essentialTypes A set of essential types that must be present in the combination. + * @param typesToCombine A set of types that should be considered for combination. + * @param maxDistanceBetweenParts The maximum distance allowed between parts to consider them for combination. + * @param minPartsToCombine The minimum number of parts that must be combined. + * @return A stream of combined {@link TextEntity} objects that match the specified criteria. + */ + public Stream combineNerEntities(NerEntities nerEntities, + String type, + EntityType entityType, + SemanticNode semanticNode, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine) { + + return NerEntitiesAdapter.combineNerEntitiesOfAllGivenTypes(nerEntities, essentialTypes, typesToCombine, maxDistanceBetweenParts, minPartsToCombine) + .map(boundary -> byTextRangeWithEngine(boundary, type, entityType, semanticNode, Set.of(Engine.NER))) + .filter(Optional::isPresent) + .map(Optional::get); + } + + + /** + * Combines multiple NER entities into a single text entity based on the specified types, maximum distance between parts, minimum parts to combine, and minimum essential types combined. + * + * @param nerEntities The collection of NER entities to combine. + * @param type The type for the combined entity. + * @param entityType The classification for the combined entity. + * @param semanticNode The semantic node related to these entities. + * @param essentialTypes A set of essential types that must be present in the combination. + * @param typesToCombine A set of types that should be considered for combination. + * @param maxDistanceBetweenParts The maximum distance allowed between parts to consider them for combination. + * @param minPartsToCombine The minimum number of parts that must be combined. + * @param minEssentialTypesCombined The minimum number of essential types that must be combined. + * @return A stream of combined {@link TextEntity} objects that match the specified criteria. + */ + public Stream combineNerEntities(NerEntities nerEntities, + String type, + EntityType entityType, + SemanticNode semanticNode, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined) { + + return NerEntitiesAdapter.combineNerEntitiesOfAllGivenTypes(nerEntities, + essentialTypes, + typesToCombine, + maxDistanceBetweenParts, + minPartsToCombine, + minEssentialTypesCombined) + .map(boundary -> byTextRangeWithEngine(boundary, type, entityType, semanticNode, Set.of(Engine.NER))) + .filter(Optional::isPresent) + .map(Optional::get); + } + + + /** + * Combines multiple NER entities into a single text entity based on the specified types, maximum distance between parts, minimum parts to combine, minimum essential types combined, and confidence level. + * + * @param nerEntities The collection of NER entities to combine. + * @param type The type for the combined entity. + * @param entityType The classification for the combined entity. + * @param semanticNode The semantic node related to these entities. + * @param essentialTypes A set of essential types that must be present in the combination. + * @param typesToCombine A set of types that should be considered for combination. + * @param maxDistanceBetweenParts The maximum distance allowed between parts to consider them for combination. + * @param minPartsToCombine The minimum number of parts that must be combined. + * @param minEssentialTypesCombined The minimum number of essential types that must be combined. + * @param confidence The confidence level required for combining entities. + * @return A stream of combined {@link TextEntity} objects that match the specified criteria and confidence level. + */ + public Stream combineNerEntitiesWithConfidence(NerEntities nerEntities, + String type, + EntityType entityType, + SemanticNode semanticNode, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined, + Double confidence) { + + return NerEntitiesAdapter.combineNerEntitiesOfAllGivenTypesWithConfidence(nerEntities, + essentialTypes, + typesToCombine, + maxDistanceBetweenParts, + minPartsToCombine, + minEssentialTypesCombined, + confidence) + .map(boundary -> byTextRangeWithEngine(boundary, type, entityType, semanticNode, Set.of(Engine.NER))) + .filter(Optional::isPresent) + .map(Optional::get); + } + + /** * Validates if a given text range within a text block represents a valid entity. * diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/NerEntitiesAdapter.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/NerEntitiesAdapter.java index 37eb8432..d3c3151f 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/NerEntitiesAdapter.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/service/document/NerEntitiesAdapter.java @@ -19,6 +19,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.NodeType; import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode; import lombok.AccessLevel; +import lombok.NonNull; import lombok.experimental.FieldDefaults; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; @@ -35,6 +36,7 @@ public class NerEntitiesAdapter { static int MAX_DISTANCE_BETWEEN_PARTS = 20; static int MIN_PARTS_TO_COMBINE = 3; static boolean ALLOW_DUPLICATES; + static int MIN_ESSENTIAL_TYPES_COMBINED; /** @@ -49,7 +51,8 @@ public class NerEntitiesAdapter { return new NerEntities(addOffsetsAndFlatten(getStringStartOffsetsForMainSectionsHeadersFooters(document), nerEntitiesModel).map(nerEntityModel -> new NerEntities.NerEntity( nerEntityModel.getValue(), new TextRange(nerEntityModel.getStartOffset(), nerEntityModel.getEndOffset()), - nerEntityModel.getType())) + nerEntityModel.getType(), + nerEntityModel.getConfidence())) .toList()); } @@ -60,12 +63,13 @@ public class NerEntitiesAdapter { * The first part must be an EntityRecognitionEntity of an essential type. * The resulting list must consist of at least minPartsToCombine parts. * - * @param nerEntities already validated entities from the NER Service - * @param essentialTypes the combined entities must contain at least one of these types - * @param typesToCombine all types which should be used to combine, must contain all essentialTypes - * @param maxDistanceBetweenParts all parts used to combine should be at most this value apart in string offset coordinates - * @param minPartsToCombine minimum number of parts to combine - * @param allowDuplicates allow combining multiple parts of same type + * @param nerEntities already validated entities from the NER Service + * @param essentialTypes the combined entities must contain at least one of these types + * @param typesToCombine all types which should be used to combine, must contain all essentialTypes + * @param maxDistanceBetweenParts all parts used to combine should be at most this value apart in string offset coordinates + * @param minPartsToCombine minimum number of parts to combine + * @param minEssentialTypesCombined minimum number of essential types that must be part of a combination + * @param allowDuplicates allow combining multiple parts of same type * @return A Stream of the combined boundaries */ public Stream combineNerEntities(NerEntities nerEntities, @@ -73,51 +77,107 @@ public class NerEntitiesAdapter { Set typesToCombine, int maxDistanceBetweenParts, int minPartsToCombine, + int minEssentialTypesCombined, boolean allowDuplicates) { - List sortedEntities = nerEntities.getNerEntityList() - .stream() - .filter(entity -> typesToCombine.contains(entity.type())) - .sorted(Comparator.comparingInt(entity -> entity.textRange().start())) - .toList(); + return getTextRangeStream(nerEntities, essentialTypes, typesToCombine, maxDistanceBetweenParts, minPartsToCombine, minEssentialTypesCombined, allowDuplicates); + + } + + + @NonNull + private static Stream getTextRangeStream(NerEntities nerEntities, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined, + boolean allowDuplicates) { + + List sortedEntities = getSortedEntities(nerEntities, typesToCombine); if (sortedEntities.isEmpty()) { return Stream.empty(); } - List> entityClusters = new LinkedList<>(); - - List startEntitiesOfEssentialType = sortedEntities.stream() - .filter(e -> essentialTypes.contains(e.type())) - .toList(); - for (NerEntities.NerEntity startEntity : startEntitiesOfEssentialType) { - List currentCluster = new LinkedList<>(); - entityClusters.add(currentCluster); - int lastEndOffset = startEntity.textRange().end(); - - for (NerEntities.NerEntity entity : sortedEntities) { - if (entity.textRange().start() < lastEndOffset) { - continue; - } - if (distanceIsLargerThanMaxDistance(lastEndOffset, entity, maxDistanceBetweenParts) || isDuplicate(currentCluster, entity, allowDuplicates)) { - currentCluster = new LinkedList<>(); - entityClusters.add(currentCluster); - currentCluster.add(entity); - lastEndOffset = entity.textRange().end(); - } else { - currentCluster.add(entity); - lastEndOffset = entity.textRange().end(); - } - } - } + List> entityClusters = getEntityClusters(essentialTypes, + maxDistanceBetweenParts, + minPartsToCombine, + minEssentialTypesCombined, + allowDuplicates, + sortedEntities); return entityClusters.stream() - .filter(cluster -> cluster.size() >= minPartsToCombine) .map(NerEntitiesAdapter::toContainingBoundary) .distinct(); } + private static List getSortedEntities(NerEntities nerEntities, Set typesToCombine) { + + return nerEntities.getNerEntityList() + .stream() + .filter(entity -> typesToCombine.contains(entity.type())) + .sorted(Comparator.comparingInt(entity -> entity.textRange().start())) + .toList(); + } + + + private static List> getEntityClusters(Set essentialTypes, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined, + boolean allowDuplicates, + List sortedEntities) { + + List> entityClusters = new LinkedList<>(); + List currentCluster = new LinkedList<>(); + int lastEndOffset = -1; + + for (NerEntities.NerEntity entity : sortedEntities) { + + // cluster can be added as it is either duplicated or distance is too large + if (!currentCluster.isEmpty() && (distanceIsLargerThanMaxDistance(lastEndOffset, entity, maxDistanceBetweenParts) || isDuplicate(currentCluster, + entity, + allowDuplicates))) { + entityClusters.add(new LinkedList<>(currentCluster)); + currentCluster.clear(); + } + + currentCluster.add(entity); + lastEndOffset = entity.textRange().end(); + } + + // add the last cluster if not empty + if (!currentCluster.isEmpty()) { + entityClusters.add(currentCluster); + } + + return filterClusters(entityClusters, essentialTypes, minPartsToCombine, minEssentialTypesCombined); + } + + + private static List> filterClusters(List> clusters, + Set essentialTypes, + int minPartsToCombine, + int minEssentialTypesCombined) { + + return clusters.stream() + .filter(cluster -> cluster.size() >= minPartsToCombine) + .filter(cluster -> countEssentialEntities(cluster, essentialTypes) >= minEssentialTypesCombined) + .distinct() + .toList(); + } + + + private static long countEssentialEntities(List cluster, Set essentialTypes) { + + return cluster.stream() + .filter(entity -> essentialTypes.contains(entity.type())) + .count(); + } + + /** * Calls combine NerEntities with the following settings. *

@@ -137,6 +197,76 @@ public class NerEntitiesAdapter { CBI_ADDRESS_TYPES_TO_COMBINE, MAX_DISTANCE_BETWEEN_PARTS, MIN_PARTS_TO_COMBINE, + MIN_ESSENTIAL_TYPES_COMBINED, + ALLOW_DUPLICATES); + } + + + public Stream combineNerEntitiesOfAllGivenTypes(NerEntities entityRecognitionEntities, + Set essentialTypes, + Set typesToCombine, + int minPartsToCombine) { + + return combineNerEntities(entityRecognitionEntities, + essentialTypes, + typesToCombine, + MAX_DISTANCE_BETWEEN_PARTS, + minPartsToCombine, + MIN_ESSENTIAL_TYPES_COMBINED, + ALLOW_DUPLICATES); + } + + + public Stream combineNerEntitiesOfAllGivenTypes(NerEntities entityRecognitionEntities, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine) { + + return combineNerEntities(entityRecognitionEntities, + essentialTypes, + typesToCombine, + maxDistanceBetweenParts, + minPartsToCombine, + MIN_ESSENTIAL_TYPES_COMBINED, + ALLOW_DUPLICATES); + } + + + public Stream combineNerEntitiesOfAllGivenTypes(NerEntities entityRecognitionEntities, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined) { + + return combineNerEntities(entityRecognitionEntities, + essentialTypes, + typesToCombine, + maxDistanceBetweenParts, + minPartsToCombine, + minEssentialTypesCombined, + ALLOW_DUPLICATES); + } + + + public Stream combineNerEntitiesOfAllGivenTypesWithConfidence(NerEntities entityRecognitionEntities, + Set essentialTypes, + Set typesToCombine, + int maxDistanceBetweenParts, + int minPartsToCombine, + int minEssentialTypesCombined, + Double confidence) { + + return combineNerEntities(new NerEntities(entityRecognitionEntities.getNerEntityList() + .stream() + .filter(nerEntity -> nerEntity.confidence() == null || nerEntity.confidence() >= confidence) + .toList()), + essentialTypes, + typesToCombine, + maxDistanceBetweenParts, + minPartsToCombine, + minEssentialTypesCombined, ALLOW_DUPLICATES); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/storage/RedactionStorageService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/storage/RedactionStorageService.java index 93b816f5..e76417f3 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/storage/RedactionStorageService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/storage/RedactionStorageService.java @@ -153,14 +153,13 @@ public class RedactionStorageService { } - @Timed("redactmanager_getImportedLegalBases") public ImportedLegalBases getImportedLegalBases(String dossierId, String fileId) { try { return storageService.readJSONObject(TenantContext.getTenantId(), - StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES), - ImportedLegalBases.class); + StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES), + ImportedLegalBases.class); } catch (StorageObjectDoesNotExist e) { log.debug("Imported legal bases not available."); return new ImportedLegalBases(); @@ -295,6 +294,17 @@ public class RedactionStorageService { } + @Timed("redactmanager_getAzureNerEntities") + public NerEntitiesModel getAzureNerEntities(String dossierId, String fileId) { + + try { + return storageService.readJSONObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, FileType.AZURE_NER_ENTITIES), NerEntitiesModel.class); + } catch (StorageObjectDoesNotExist e) { + throw new NotFoundException("NER Entities are not available."); + } + } + + public ComponentLog getComponentLog(String dossierId, String fileId) { try { diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/redaction/adapter/NerEntitiesAdapterTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/redaction/adapter/NerEntitiesAdapterTest.java index 2fc5cfd0..4d00e15d 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/redaction/adapter/NerEntitiesAdapterTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/redaction/adapter/NerEntitiesAdapterTest.java @@ -6,9 +6,11 @@ import static org.wildfly.common.Assert.assertTrue; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.io.File; +import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -66,15 +68,38 @@ class NerEntitiesAdapterTest extends BuildDocumentIntegrationTest { String filePath = "files/new/crafted document.pdf"; String nerEntitiesFilePath = "ner_entities/crafted document.NER_ENTITIES.json"; Document document = buildGraphNoImages(filePath); - List entityRecognitionEntities = validateAndCombine(parseNerEntities(nerEntitiesFilePath), document); + NerEntities nerEntities = NerEntitiesAdapter.toNerEntities(parseNerEntities(nerEntitiesFilePath), document); + getNerEntitiesForFile(new ClassPathResource(filePath), document, nerEntities); + + } + + + @Test + @SneakyThrows + public void testGetAzureNerEntities() { + + String filePath = "files/new/intertek.ORIGIN.pdf"; + String nerEntitiesFilePath = "ner_entities/intertek.NER_ENTITIES.json"; + String azureNerEntitiesFilePath = "ner_entities/intertek.AZURE_NER_ENTITIES.json"; + Document document = buildGraphNoImages(filePath); + NerEntities azureNerEntities = NerEntitiesAdapter.toNerEntities(parseNerEntities(azureNerEntitiesFilePath), document); + NerEntities nerEntities = NerEntitiesAdapter.toNerEntities(parseNerEntities(nerEntitiesFilePath), document); + nerEntities.merge(azureNerEntities); + getNerEntitiesForFile(new ClassPathResource(filePath), document, nerEntities); + + } + + + private void getNerEntitiesForFile(ClassPathResource resource, Document document, NerEntities nerEntities) throws IOException { + + List entityRecognitionEntities = validateAndCombine(nerEntities, document); assertFalse(entityRecognitionEntities.isEmpty()); assertTrue(entityRecognitionEntities.stream() .allMatch(entity -> entity.textRange().start() < entity.textRange().end())); - ClassPathResource resource = new ClassPathResource(filePath); try (PDDocument pdDocument = Loader.loadPDF(resource.getFile())) { - Stream unchangedAddressParts = NerEntitiesAdapter.toNerEntities(parseNerEntities(nerEntitiesFilePath), document).getNerEntityList() + Stream unchangedAddressParts = nerEntities.getNerEntityList() .stream() .filter(e -> !e.type().equals("CBI_author")); List redactionEntities = Stream.concat(entityRecognitionEntities.stream(), unchangedAddressParts) @@ -96,7 +121,6 @@ class NerEntitiesAdapterTest extends BuildDocumentIntegrationTest { File outputFile = new File("/tmp/nerEntities.pdf"); pdDocument.save(outputFile); } - } @@ -150,16 +174,37 @@ class NerEntitiesAdapterTest extends BuildDocumentIntegrationTest { } - private List validateAndCombine(NerEntitiesModel nerEntitiesModel, Document document) { - - NerEntities nerEntities = NerEntitiesAdapter.toNerEntities(nerEntitiesModel, document); + private List validateAndCombine(NerEntities nerEntities, Document document) { List cbiAuthors = nerEntities.streamEntitiesOfType("CBI_author") .toList(); Stream cbiAddress = NerEntitiesAdapter.combineNerEntitiesToCbiAddressDefaults(nerEntities) .map(boundary -> new NerEntities.NerEntity(document.getTextBlock().subSequence(boundary).toString(), boundary, "CBI_address")); + Stream azureCbiAddress = NerEntitiesAdapter.combineNerEntitiesOfAllGivenTypesWithConfidence(nerEntities, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "Quantity", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .map(boundary -> new NerEntities.NerEntity(document.getTextBlock().subSequence(boundary).toString(), boundary, "CBI_address")); - return Stream.concat(cbiAuthors.stream(), cbiAddress) + return Stream.concat(cbiAuthors.stream(), Stream.concat(cbiAddress, azureCbiAddress)) .toList(); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/acceptance_rules.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/acceptance_rules.drl index 0ab463d6..68bb9fbb 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/acceptance_rules.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/acceptance_rules.drl @@ -1084,6 +1084,84 @@ rule "AI.1.0: Combine and add NER Entities as CBI_address" end +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/all_redact_manager_rules.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/all_redact_manager_rules.drl index 5d9ac5c0..b26c04e7 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/all_redact_manager_rules.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/all_redact_manager_rules.drl @@ -1738,6 +1738,84 @@ rule "AI.3.0: Recommend authors from AI as PII" end +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/documine_flora.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/documine_flora.drl index 1eff5d4a..72276637 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/documine_flora.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/documine_flora.drl @@ -1149,6 +1149,86 @@ rule "DOC.35.0: Doses (mg/kg bodyweight)" end +//------------------------------------ AI rules ------------------------------------ + +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/efsa_sanitisation.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/efsa_sanitisation.drl index 5b5c14d6..22f3dbff 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/efsa_sanitisation.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/efsa_sanitisation.drl @@ -643,6 +643,84 @@ rule "AI.1.0: Combine and add NER Entities as CBI_address" end +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/manual_redaction_rules.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/manual_redaction_rules.drl index b42602ba..02166d95 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/manual_redaction_rules.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/manual_redaction_rules.drl @@ -69,6 +69,86 @@ query "getFileAttributes" $fileAttribute: FileAttribute() end +//------------------------------------ AI rules ------------------------------------ + +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules.drl index 6616c138..182faee1 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules.drl @@ -1173,6 +1173,85 @@ rule "AI.1.0: Combine and add NER Entities as CBI_address" end +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules_v2.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules_v2.drl index 0c9b0b67..663b9b6d 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules_v2.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/rules_v2.drl @@ -108,6 +108,84 @@ rule "AI.0.0: Add all NER Entities of type CBI_author" end +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/table_demo.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/table_demo.drl index aca5480f..0f75054e 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/table_demo.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/table_demo.drl @@ -219,6 +219,86 @@ rule "TAB.7.0: Indicator (Species)" end +//------------------------------------ AI rules ------------------------------------ + +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/test_rules.drl b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/test_rules.drl index 1c6dcd8f..d00f0fdc 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/test_rules.drl +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools/test_rules.drl @@ -119,6 +119,86 @@ rule "TAB.6.0: Targeted cell extraction (Experimental Stop date)" end +//------------------------------------ AI rules ------------------------------------ + +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual changes rules ------------------------------------ // Rule unit: MAN.0 diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/new/intertek.ORIGIN.pdf b/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/new/intertek.ORIGIN.pdf new file mode 100644 index 00000000..99ccf2c1 Binary files /dev/null and b/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/new/intertek.ORIGIN.pdf differ diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.AZURE_NER_ENTITIES.json b/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.AZURE_NER_ENTITIES.json new file mode 100644 index 00000000..592a87a0 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.AZURE_NER_ENTITIES.json @@ -0,0 +1,6086 @@ +{ + "data": { + "2.1.11.3": [ + { + "value": "1", + "startOffset": 58, + "endOffset": 59, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 70, + "endOffset": 71, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 147, + "endOffset": 148, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicants", + "startOffset": 151, + "endOffset": 161, + "type": "PersonType", + "confidence": 0.85 + }, + { + "value": "manufacturers", + "startOffset": 163, + "endOffset": 176, + "type": "PersonType", + "confidence": 0.5 + }, + { + "value": "person", + "startOffset": 232, + "endOffset": 238, + "type": "PersonType", + "confidence": 0.65 + }, + { + "value": "3.2.2.1", + "startOffset": 406, + "endOffset": 413, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "34", + "startOffset": 419, + "endOffset": 421, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "to 36", + "startOffset": 422, + "endOffset": 427, + "type": "Quantity", + "confidence": 0.52 + }, + { + "value": "Manufacturing process", + "startOffset": 428, + "endOffset": 449, + "type": "Skill", + "confidence": 1.0 + }, + { + "value": "manufacturing process", + "startOffset": 478, + "endOffset": 499, + "type": "Skill", + "confidence": 1.0 + }, + { + "value": "3.2.2.2", + "startOffset": 504, + "endOffset": 511, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "3.2.2.2", + "startOffset": 572, + "endOffset": 579, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 580, + "endOffset": 581, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicant", + "startOffset": 622, + "endOffset": 631, + "type": "PersonType", + "confidence": 0.84 + }, + { + "value": "3.2.2.1", + "startOffset": 640, + "endOffset": 647, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 648, + "endOffset": 649, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.1.2.2", + "startOffset": 697, + "endOffset": 704, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 705, + "endOffset": 706, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2.2.2", + "startOffset": 758, + "endOffset": 765, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 766, + "endOffset": 767, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Particle size", + "startOffset": 768, + "endOffset": 781, + "type": "Skill", + "confidence": 0.82 + }, + { + "value": "30", + "startOffset": 787, + "endOffset": 789, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "31", + "startOffset": 794, + "endOffset": 796, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Particle size analysis", + "startOffset": 797, + "endOffset": 819, + "type": "Skill", + "confidence": 0.7 + }, + { + "value": "internal stability", + "startOffset": 824, + "endOffset": 842, + "type": "Skill", + "confidence": 0.64 + }, + { + "value": "3", + "startOffset": 944, + "endOffset": 945, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 946, + "endOffset": 947, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 948, + "endOffset": 949, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicant", + "startOffset": 987, + "endOffset": 996, + "type": "PersonType", + "confidence": 0.97 + }, + { + "value": "3", + "startOffset": 1009, + "endOffset": 1010, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1011, + "endOffset": 1012, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1013, + "endOffset": 1014, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1058, + "endOffset": 1059, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1064, + "endOffset": 1065, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1066, + "endOffset": 1067, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1068, + "endOffset": 1069, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1070, + "endOffset": 1071, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1125, + "endOffset": 1126, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1127, + "endOffset": 1128, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1129, + "endOffset": 1130, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1131, + "endOffset": 1132, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1140, + "endOffset": 1141, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1142, + "endOffset": 1143, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1144, + "endOffset": 1145, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1146, + "endOffset": 1147, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "41", + "startOffset": 1153, + "endOffset": 1155, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "cassia gum", + "startOffset": 1169, + "endOffset": 1179, + "type": "Product", + "confidence": 0.93 + }, + { + "value": "sauce", + "startOffset": 1244, + "endOffset": 1249, + "type": "Product", + "confidence": 0.85 + }, + { + "value": "3", + "startOffset": 1307, + "endOffset": 1308, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1309, + "endOffset": 1310, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1311, + "endOffset": 1312, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1313, + "endOffset": 1314, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicant", + "startOffset": 1351, + "endOffset": 1360, + "type": "PersonType", + "confidence": 0.84 + }, + { + "value": "data", + "startOffset": 1387, + "endOffset": 1391, + "type": "Skill", + "confidence": 0.8 + }, + { + "value": "3.5.1.4", + "startOffset": 1462, + "endOffset": 1469, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "42", + "startOffset": 1475, + "endOffset": 1477, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Sales data", + "startOffset": 1478, + "endOffset": 1488, + "type": "Skill", + "confidence": 0.58 + }, + { + "value": "sales", + "startOffset": 1498, + "endOffset": 1503, + "type": "Skill", + "confidence": 0.74 + }, + { + "value": "data", + "startOffset": 1504, + "endOffset": 1508, + "type": "Skill", + "confidence": 0.65 + }, + { + "value": "applicant", + "startOffset": 1599, + "endOffset": 1608, + "type": "PersonType", + "confidence": 0.7 + }, + { + "value": "internal study", + "startOffset": 1673, + "endOffset": 1687, + "type": "Skill", + "confidence": 0.5 + }, + { + "value": "reports", + "startOffset": 1779, + "endOffset": 1786, + "type": "Skill", + "confidence": 0.9 + }, + { + "value": "applicant", + "startOffset": 1794, + "endOffset": 1803, + "type": "PersonType", + "confidence": 0.72 + }, + { + "value": "applicants", + "startOffset": 1964, + "endOffset": 1974, + "type": "PersonType", + "confidence": 0.95 + }, + { + "value": "data", + "startOffset": 2001, + "endOffset": 2005, + "type": "Skill", + "confidence": 0.8 + } + ], + "2.1.10.4": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "234/2011", + "startOffset": 79, + "endOffset": 87, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 109, + "endOffset": 118, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 129, + "endOffset": 133, + "type": "Organization", + "confidence": 0.92 + }, + { + "value": "EFSA", + "startOffset": 189, + "endOffset": 193, + "type": "Organization", + "confidence": 0.94 + }, + { + "value": "ANS Panel", + "startOffset": 194, + "endOffset": 203, + "type": "Organization", + "confidence": 0.83 + }, + { + "value": "2021", + "startOffset": 205, + "endOffset": 209, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "234/2011", + "startOffset": 278, + "endOffset": 286, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 338, + "endOffset": 347, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicants", + "startOffset": 392, + "endOffset": 402, + "type": "PersonType", + "confidence": 0.52 + }, + { + "value": "EFSA", + "startOffset": 433, + "endOffset": 437, + "type": "Organization", + "confidence": 0.97 + }, + { + "value": "additives", + "startOffset": 477, + "endOffset": 486, + "type": "Product", + "confidence": 0.5 + }, + { + "value": "2.2.9.5", + "startOffset": 628, + "endOffset": 635, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "3.13", + "startOffset": 676, + "endOffset": 680, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.4", + "startOffset": 689, + "endOffset": 692, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 693, + "endOffset": 694, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 695, + "endOffset": 696, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10", + "startOffset": 697, + "endOffset": 699, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.16", + "startOffset": 754, + "endOffset": 758, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 767, + "endOffset": 768, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 769, + "endOffset": 770, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 771, + "endOffset": 772, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "11", + "startOffset": 773, + "endOffset": 775, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.15", + "startOffset": 840, + "endOffset": 844, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 845, + "endOffset": 846, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 847, + "endOffset": 848, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "12", + "startOffset": 849, + "endOffset": 851, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.8", + "startOffset": 914, + "endOffset": 917, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 918, + "endOffset": 919, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 920, + "endOffset": 921, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "13", + "startOffset": 922, + "endOffset": 924, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1045, + "endOffset": 1046, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.3", + "startOffset": 1049, + "endOffset": 1052, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Risk management", + "startOffset": 1053, + "endOffset": 1068, + "type": "Skill", + "confidence": 0.97 + }, + { + "value": "4", + "startOffset": 1079, + "endOffset": 1080, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1081, + "endOffset": 1082, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1083, + "endOffset": 1084, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1085, + "endOffset": 1086, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.1", + "startOffset": 1154, + "endOffset": 1157, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1166, + "endOffset": 1167, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1183, + "endOffset": 1184, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1185, + "endOffset": 1186, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1187, + "endOffset": 1188, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.1", + "startOffset": 1257, + "endOffset": 1260, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1427, + "endOffset": 1428, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1429, + "endOffset": 1430, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1431, + "endOffset": 1432, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.2", + "startOffset": 1502, + "endOffset": 1505, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1543, + "endOffset": 1544, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1545, + "endOffset": 1546, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1547, + "endOffset": 1548, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "consumer", + "startOffset": 1581, + "endOffset": 1589, + "type": "PersonType", + "confidence": 0.95 + }, + { + "value": "4.3", + "startOffset": 1607, + "endOffset": 1610, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 1645, + "endOffset": 1646, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1648, + "endOffset": 1649, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 1673, + "endOffset": 1682, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1683, + "endOffset": 1684, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1685, + "endOffset": 1686, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "5", + "startOffset": 1687, + "endOffset": 1688, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "consumer", + "startOffset": 1735, + "endOffset": 1743, + "type": "PersonType", + "confidence": 0.94 + }, + { + "value": "4.4", + "startOffset": 1744, + "endOffset": 1747, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1748, + "endOffset": 1749, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1750, + "endOffset": 1751, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 1752, + "endOffset": 1753, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.5", + "startOffset": 1816, + "endOffset": 1819, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1828, + "endOffset": 1829, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 1874, + "endOffset": 1883, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "one", + "startOffset": 1968, + "endOffset": 1971, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1992, + "endOffset": 1993, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1994, + "endOffset": 1995, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 1996, + "endOffset": 1997, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.6", + "startOffset": 2061, + "endOffset": 2064, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2110, + "endOffset": 2111, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2112, + "endOffset": 2113, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "8", + "startOffset": 2114, + "endOffset": 2115, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.7", + "startOffset": 2182, + "endOffset": 2185, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.4", + "startOffset": 2194, + "endOffset": 2197, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "consumer", + "startOffset": 2205, + "endOffset": 2213, + "type": "PersonType", + "confidence": 0.92 + }, + { + "value": "2", + "startOffset": 2214, + "endOffset": 2215, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2216, + "endOffset": 2217, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "9", + "startOffset": 2218, + "endOffset": 2219, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.3", + "startOffset": 2289, + "endOffset": 2292, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.8", + "startOffset": 2297, + "endOffset": 2300, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2338, + "endOffset": 2339, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2340, + "endOffset": 2341, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10", + "startOffset": 2342, + "endOffset": 2344, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.9", + "startOffset": 2412, + "endOffset": 2415, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 2428, + "endOffset": 2429, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 2452, + "endOffset": 2461, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2462, + "endOffset": 2463, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2464, + "endOffset": 2465, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "11", + "startOffset": 2466, + "endOffset": 2468, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.10", + "startOffset": 2533, + "endOffset": 2537, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "8", + "startOffset": 2550, + "endOffset": 2551, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 2574, + "endOffset": 2583, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 2618, + "endOffset": 2622, + "type": "Organization", + "confidence": 0.98 + }, + { + "value": "European Food Safety Authority", + "startOffset": 2625, + "endOffset": 2655, + "type": "Organization", + "confidence": 0.99 + }, + { + "value": "INS", + "startOffset": 2657, + "endOffset": 2660, + "type": "Organization", + "confidence": 0.88 + }, + { + "value": "Food Additives", + "startOffset": 2698, + "endOffset": 2712, + "type": "Product", + "confidence": 0.56 + }, + { + "value": "Commission", + "startOffset": 2738, + "endOffset": 2748, + "type": "Organization", + "confidence": 0.5 + }, + { + "value": "234/2011", + "startOffset": 2768, + "endOffset": 2776, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10 March 2011", + "startOffset": 2780, + "endOffset": 2793, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "1331/2008", + "startOffset": 2826, + "endOffset": 2835, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 2843, + "endOffset": 2862, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 2874, + "endOffset": 2881, + "type": "Organization", + "confidence": 0.88 + }, + { + "value": "64", + "startOffset": 2988, + "endOffset": 2990, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "11.3.2011", + "startOffset": 2992, + "endOffset": 3001, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "15", + "startOffset": 3006, + "endOffset": 3008, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "24", + "startOffset": 3009, + "endOffset": 3011, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "http://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX:32011R0234", + "startOffset": 3031, + "endOffset": 3098, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "18/07/2012", + "startOffset": 3122, + "endOffset": 3132, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "1333/2008", + "startOffset": 3156, + "endOffset": 3165, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 3173, + "endOffset": 3192, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 3204, + "endOffset": 3211, + "type": "Organization", + "confidence": 0.75 + }, + { + "value": "16 December 2008", + "startOffset": 3215, + "endOffset": 3231, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "food additives", + "startOffset": 3235, + "endOffset": 3249, + "type": "Product", + "confidence": 0.71 + }, + { + "value": "354", + "startOffset": 3256, + "endOffset": 3259, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "31.12.2008", + "startOffset": 3261, + "endOffset": 3271, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "16", + "startOffset": 3276, + "endOffset": 3278, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "–", + "startOffset": 3278, + "endOffset": 3279, + "type": "Quantity", + "confidence": 0.51 + }, + { + "value": "33", + "startOffset": 3279, + "endOffset": 3281, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "http://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX:32008R1333&qid=1437074262608", + "startOffset": 3301, + "endOffset": 3386, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "25/03/2020", + "startOffset": 3410, + "endOffset": 3420, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "1829/2003", + "startOffset": 3444, + "endOffset": 3453, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 3461, + "endOffset": 3480, + "type": "Organization", + "confidence": 0.99 + }, + { + "value": "Council", + "startOffset": 3492, + "endOffset": 3499, + "type": "Organization", + "confidence": 0.65 + }, + { + "value": "22 September 2003", + "startOffset": 3503, + "endOffset": 3520, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "268", + "startOffset": 3565, + "endOffset": 3568, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "18.10.2003", + "startOffset": 3570, + "endOffset": 3580, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "1", + "startOffset": 3585, + "endOffset": 3586, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "23", + "startOffset": 3587, + "endOffset": 3589, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "https://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX%3A32003R1829", + "startOffset": 3609, + "endOffset": 3679, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "10/04/2008", + "startOffset": 3703, + "endOffset": 3713, + "type": "DateTime", + "confidence": 0.94 + }, + { + "value": "178/2002", + "startOffset": 3737, + "endOffset": 3745, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 3753, + "endOffset": 3772, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "28 January 2002", + "startOffset": 3795, + "endOffset": 3810, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "European Food Safety Authority", + "startOffset": 3893, + "endOffset": 3923, + "type": "Organization", + "confidence": 0.98 + } + ], + "2.1.7": [ + { + "value": "2", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2, + "endOffset": 3, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1829/2003", + "startOffset": 61, + "endOffset": 70, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.10.5": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "234/2011", + "startOffset": 79, + "endOffset": 87, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 109, + "endOffset": 118, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 129, + "endOffset": 133, + "type": "Organization", + "confidence": 0.95 + }, + { + "value": "EFSA ANS Panel", + "startOffset": 189, + "endOffset": 203, + "type": "Organization", + "confidence": 0.63 + }, + { + "value": "2021", + "startOffset": 205, + "endOffset": 209, + "type": "DateTime", + "confidence": 0.96 + }, + { + "value": "234/2011", + "startOffset": 278, + "endOffset": 286, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 338, + "endOffset": 347, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 433, + "endOffset": 437, + "type": "Organization", + "confidence": 0.91 + }, + { + "value": "food additives", + "startOffset": 472, + "endOffset": 486, + "type": "Product", + "confidence": 0.71 + }, + { + "value": "food enzymes", + "startOffset": 488, + "endOffset": 500, + "type": "Product", + "confidence": 0.62 + }, + { + "value": "food", + "startOffset": 505, + "endOffset": 509, + "type": "Product", + "confidence": 0.51 + }, + { + "value": "food additive", + "startOffset": 602, + "endOffset": 615, + "type": "Product", + "confidence": 0.65 + }, + { + "value": "31", + "startOffset": 657, + "endOffset": 659, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.2.2002", + "startOffset": 661, + "endOffset": 669, + "type": "DateTime", + "confidence": 0.88 + }, + { + "value": "1", + "startOffset": 674, + "endOffset": 675, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "24", + "startOffset": 676, + "endOffset": 678, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "https://eur-lex.europa.eu/legalcontent/EN/TXT/?qid=1583435888964&uri=CELEX:32002R0178", + "startOffset": 698, + "endOffset": 783, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "01/07/2022", + "startOffset": 815, + "endOffset": 825, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "1333/2008", + "startOffset": 849, + "endOffset": 858, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 866, + "endOffset": 885, + "type": "Organization", + "confidence": 0.99 + }, + { + "value": "Council", + "startOffset": 897, + "endOffset": 904, + "type": "Organization", + "confidence": 0.76 + }, + { + "value": "16 December 2008", + "startOffset": 908, + "endOffset": 924, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "food additives", + "startOffset": 928, + "endOffset": 942, + "type": "Product", + "confidence": 0.74 + }, + { + "value": "354", + "startOffset": 949, + "endOffset": 952, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "31.12.2008", + "startOffset": 954, + "endOffset": 964, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "16", + "startOffset": 969, + "endOffset": 971, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "–", + "startOffset": 971, + "endOffset": 972, + "type": "Quantity", + "confidence": 0.51 + }, + { + "value": "33", + "startOffset": 972, + "endOffset": 974, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "http://eur-lex.europa.eu/legalcontent/EN/ALL/?uri=CELEX:32008R1333&qid=1437074262608", + "startOffset": 994, + "endOffset": 1078, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "23/12/2020", + "startOffset": 1110, + "endOffset": 1120, + "type": "DateTime", + "confidence": 1.0 + } + ], + "2.1.8": [ + { + "value": "Cassia gum", + "startOffset": 35, + "endOffset": 45, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "genetic modification", + "startOffset": 67, + "endOffset": 87, + "type": "Skill", + "confidence": 0.69 + }, + { + "value": "genetically modified", + "startOffset": 96, + "endOffset": 116, + "type": "Skill", + "confidence": 0.61 + }, + { + "value": "2", + "startOffset": 126, + "endOffset": 127, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1829/2003", + "startOffset": 147, + "endOffset": 156, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 164, + "endOffset": 183, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 195, + "endOffset": 202, + "type": "Organization", + "confidence": 0.68 + }, + { + "value": "22 September 2003", + "startOffset": 206, + "endOffset": 223, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "268", + "startOffset": 268, + "endOffset": 271, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "18.10.2003", + "startOffset": 273, + "endOffset": 283, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "1", + "startOffset": 288, + "endOffset": 289, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "23", + "startOffset": 290, + "endOffset": 292, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "https://eur-lex.europa.eu/legalcontent/EN/TXT/?uri=CELEX%3A32003R1829&qid=1614195740724", + "startOffset": 312, + "endOffset": 399, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "10/04/2008", + "startOffset": 436, + "endOffset": 446, + "type": "DateTime", + "confidence": 0.99 + } + ], + "2.1.11.1": [ + { + "value": "applicant", + "startOffset": 188, + "endOffset": 197, + "type": "PersonType", + "confidence": 0.99 + }, + { + "value": "1", + "startOffset": 250, + "endOffset": 251, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 254, + "endOffset": 255, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.10.2": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Technical Dossier", + "startOffset": 461, + "endOffset": 478, + "type": "Skill", + "confidence": 0.51 + }, + { + "value": "1331/20083", + "startOffset": 593, + "endOffset": 603, + "type": "PhoneNumber", + "confidence": 0.8 + }, + { + "value": "authorisation procedure", + "startOffset": 625, + "endOffset": 648, + "type": "Skill", + "confidence": 0.76 + }, + { + "value": "assessment", + "startOffset": 657, + "endOffset": 667, + "type": "Skill", + "confidence": 0.58 + }, + { + "value": "Data", + "startOffset": 705, + "endOffset": 709, + "type": "Skill", + "confidence": 0.66 + }, + { + "value": "application", + "startOffset": 727, + "endOffset": 738, + "type": "Skill", + "confidence": 0.59 + }, + { + "value": "234/20114", + "startOffset": 796, + "endOffset": 805, + "type": "PhoneNumber", + "confidence": 0.8 + }, + { + "value": "risk assessment", + "startOffset": 851, + "endOffset": 866, + "type": "Skill", + "confidence": 0.77 + }, + { + "value": "risk management", + "startOffset": 872, + "endOffset": 887, + "type": "Skill", + "confidence": 0.96 + }, + { + "value": "food", + "startOffset": 906, + "endOffset": 910, + "type": "Product", + "confidence": 0.5 + }, + { + "value": "EFSA", + "startOffset": 942, + "endOffset": 946, + "type": "Organization", + "confidence": 0.98 + }, + { + "value": "EFSA", + "startOffset": 1002, + "endOffset": 1006, + "type": "Organization", + "confidence": 0.93 + }, + { + "value": "ANS Panel", + "startOffset": 1007, + "endOffset": 1016, + "type": "Organization", + "confidence": 0.64 + }, + { + "value": "2021", + "startOffset": 1018, + "endOffset": 1022, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "technical application", + "startOffset": 1030, + "endOffset": 1051, + "type": "Skill", + "confidence": 0.76 + }, + { + "value": "EFSA", + "startOffset": 1101, + "endOffset": 1105, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "EFSA ANS Panel", + "startOffset": 1161, + "endOffset": 1175, + "type": "Organization", + "confidence": 0.81 + }, + { + "value": "2021", + "startOffset": 1177, + "endOffset": 1181, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "risk management", + "startOffset": 1244, + "endOffset": 1259, + "type": "Skill", + "confidence": 0.97 + }, + { + "value": "234/2011", + "startOffset": 1306, + "endOffset": 1314, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicants", + "startOffset": 1378, + "endOffset": 1388, + "type": "PersonType", + "confidence": 0.95 + }, + { + "value": "food additives", + "startOffset": 1426, + "endOffset": 1440, + "type": "Product", + "confidence": 0.89 + }, + { + "value": "food enzymes", + "startOffset": 1442, + "endOffset": 1454, + "type": "Product", + "confidence": 0.9 + }, + { + "value": "food flavourings", + "startOffset": 1459, + "endOffset": 1475, + "type": "Product", + "confidence": 0.79 + }, + { + "value": "5", + "startOffset": 1477, + "endOffset": 1478, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "234/2011", + "startOffset": 1552, + "endOffset": 1560, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicants", + "startOffset": 1602, + "endOffset": 1612, + "type": "PersonType", + "confidence": 0.59 + }, + { + "value": "EFSA", + "startOffset": 1788, + "endOffset": 1792, + "type": "Organization", + "confidence": 0.72 + }, + { + "value": "1", + "startOffset": 1876, + "endOffset": 1877, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1880, + "endOffset": 1881, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1883, + "endOffset": 1884, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 1904, + "endOffset": 1913, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 1921, + "endOffset": 1940, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 1952, + "endOffset": 1959, + "type": "Organization", + "confidence": 0.73 + }, + { + "value": "16 December 2008", + "startOffset": 1963, + "endOffset": 1979, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "procedure", + "startOffset": 2016, + "endOffset": 2025, + "type": "Skill", + "confidence": 0.63 + }, + { + "value": "354", + "startOffset": 2086, + "endOffset": 2089, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "31.12.2008", + "startOffset": 2091, + "endOffset": 2101, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "1", + "startOffset": 2106, + "endOffset": 2107, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 2108, + "endOffset": 2109, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 2111, + "endOffset": 2112, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Commission", + "startOffset": 2113, + "endOffset": 2123, + "type": "Organization", + "confidence": 0.6 + }, + { + "value": "EU", + "startOffset": 2136, + "endOffset": 2138, + "type": "Organization", + "confidence": 0.62 + }, + { + "value": "234/2011", + "startOffset": 2143, + "endOffset": 2151, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10 March 2011", + "startOffset": 2155, + "endOffset": 2168, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "1331/2008", + "startOffset": 2201, + "endOffset": 2210, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 2218, + "endOffset": 2237, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 2249, + "endOffset": 2256, + "type": "Organization", + "confidence": 0.96 + }, + { + "value": "authorisation", + "startOffset": 2279, + "endOffset": 2292, + "type": "Skill", + "confidence": 0.8 + }, + { + "value": "food additives", + "startOffset": 2307, + "endOffset": 2321, + "type": "Product", + "confidence": 0.65 + }, + { + "value": "food enzymes", + "startOffset": 2323, + "endOffset": 2335, + "type": "Product", + "confidence": 0.62 + }, + { + "value": "food flavourings", + "startOffset": 2340, + "endOffset": 2356, + "type": "Product", + "confidence": 0.54 + }, + { + "value": "64", + "startOffset": 2363, + "endOffset": 2365, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "11.3.2011", + "startOffset": 2367, + "endOffset": 2376, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "15", + "startOffset": 2381, + "endOffset": 2383, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "24.", + "startOffset": 2384, + "endOffset": 2387, + "type": "Quantity", + "confidence": 0.55 + }, + { + "value": "http://eur-lex.europa.eu/legalcontent/EN/ALL/?uri=CELEX:32011R0234", + "startOffset": 2406, + "endOffset": 2472, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "18/07/2012", + "startOffset": 2511, + "endOffset": 2521, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "5", + "startOffset": 2524, + "endOffset": 2525, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicants", + "startOffset": 2549, + "endOffset": 2559, + "type": "PersonType", + "confidence": 0.78 + }, + { + "value": "food additives", + "startOffset": 2597, + "endOffset": 2611, + "type": "Product", + "confidence": 0.8 + }, + { + "value": "food enzymes", + "startOffset": 2613, + "endOffset": 2625, + "type": "Product", + "confidence": 0.84 + }, + { + "value": "https://ec.europa.eu/food/document/download/73508ba7-39c2-4066-a9cb-57014456aeb3_en.", + "startOffset": 2647, + "endOffset": 2731, + "type": "URL", + "confidence": 0.8 + } + ], + "2.1.5": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "cassia gum", + "startOffset": 79, + "endOffset": 89, + "type": "Product", + "confidence": 0.98 + }, + { + "value": "food additive", + "startOffset": 95, + "endOffset": 108, + "type": "Product", + "confidence": 0.53 + }, + { + "value": "European Union", + "startOffset": 116, + "endOffset": 130, + "type": "Organization", + "confidence": 0.98 + }, + { + "value": "EU", + "startOffset": 132, + "endOffset": 134, + "type": "Organization", + "confidence": 0.9 + }, + { + "value": "1333/2008", + "startOffset": 161, + "endOffset": 170, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 172, + "endOffset": 173, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.12": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Application", + "startOffset": 49, + "endOffset": 60, + "type": "Skill", + "confidence": 0.54 + }, + { + "value": "support", + "startOffset": 95, + "endOffset": 102, + "type": "Skill", + "confidence": 0.85 + } + ], + "2.1.11.2": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.10.3": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "234/2011", + "startOffset": 79, + "endOffset": 87, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 109, + "endOffset": 118, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 129, + "endOffset": 133, + "type": "Organization", + "confidence": 0.92 + }, + { + "value": "EFSA", + "startOffset": 189, + "endOffset": 193, + "type": "Organization", + "confidence": 0.91 + }, + { + "value": "ANS Panel", + "startOffset": 194, + "endOffset": 203, + "type": "Organization", + "confidence": 0.58 + }, + { + "value": "2021", + "startOffset": 205, + "endOffset": 209, + "type": "DateTime", + "confidence": 0.94 + }, + { + "value": "234/2011", + "startOffset": 278, + "endOffset": 286, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 338, + "endOffset": 347, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 433, + "endOffset": 437, + "type": "Organization", + "confidence": 0.9 + }, + { + "value": "food additives", + "startOffset": 472, + "endOffset": 486, + "type": "Product", + "confidence": 0.6 + }, + { + "value": "enzymes", + "startOffset": 493, + "endOffset": 500, + "type": "Product", + "confidence": 0.49 + }, + { + "value": "1", + "startOffset": 628, + "endOffset": 629, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "234/2011", + "startOffset": 684, + "endOffset": 692, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 701, + "endOffset": 702, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.1", + "startOffset": 721, + "endOffset": 724, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 750, + "endOffset": 751, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 752, + "endOffset": 753, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 754, + "endOffset": 755, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 756, + "endOffset": 757, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "applicant", + "startOffset": 799, + "endOffset": 808, + "type": "PersonType", + "confidence": 0.53 + }, + { + "value": "1", + "startOffset": 809, + "endOffset": 810, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 813, + "endOffset": 814, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 815, + "endOffset": 816, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 817, + "endOffset": 818, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "manufacture", + "startOffset": 860, + "endOffset": 871, + "type": "Skill", + "confidence": 0.89 + }, + { + "value": "1", + "startOffset": 872, + "endOffset": 873, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 876, + "endOffset": 877, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 878, + "endOffset": 879, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 880, + "endOffset": 881, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 950, + "endOffset": 951, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 962, + "endOffset": 963, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 964, + "endOffset": 965, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 966, + "endOffset": 967, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 987, + "endOffset": 988, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1002, + "endOffset": 1003, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1004, + "endOffset": 1005, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1006, + "endOffset": 1007, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "5", + "startOffset": 1008, + "endOffset": 1009, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "food additive", + "startOffset": 1051, + "endOffset": 1064, + "type": "Product", + "confidence": 0.78 + }, + { + "value": "modification", + "startOffset": 1066, + "endOffset": 1078, + "type": "Event", + "confidence": 0.54 + }, + { + "value": "1", + "startOffset": 1079, + "endOffset": 1080, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "food additive", + "startOffset": 1133, + "endOffset": 1146, + "type": "Product", + "confidence": 0.76 + }, + { + "value": "2", + "startOffset": 1222, + "endOffset": 1223, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1224, + "endOffset": 1225, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 1226, + "endOffset": 1227, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1292, + "endOffset": 1293, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1321, + "endOffset": 1322, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1323, + "endOffset": 1324, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 1325, + "endOffset": 1326, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1386, + "endOffset": 1387, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1829", + "startOffset": 1393, + "endOffset": 1397, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1442, + "endOffset": 1443, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1444, + "endOffset": 1445, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "8", + "startOffset": 1446, + "endOffset": 1447, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1480, + "endOffset": 1481, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1484, + "endOffset": 1485, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1486, + "endOffset": 1487, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "9", + "startOffset": 1488, + "endOffset": 1489, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1552, + "endOffset": 1553, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "index", + "startOffset": 1629, + "endOffset": 1634, + "type": "Skill", + "confidence": 0.91 + }, + { + "value": "2", + "startOffset": 1677, + "endOffset": 1678, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1679, + "endOffset": 1680, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10", + "startOffset": 1681, + "endOffset": 1683, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1750, + "endOffset": 1751, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1840, + "endOffset": 1841, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1842, + "endOffset": 1843, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "11", + "startOffset": 1844, + "endOffset": 1846, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1915, + "endOffset": 1916, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "32b", + "startOffset": 1969, + "endOffset": 1972, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "178", + "startOffset": 1995, + "endOffset": 1998, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2", + "startOffset": 2005, + "endOffset": 2008, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2036, + "endOffset": 2037, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2042, + "endOffset": 2043, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2044, + "endOffset": 2045, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2046, + "endOffset": 2047, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2048, + "endOffset": 2049, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.1", + "startOffset": 2120, + "endOffset": 2123, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2", + "startOffset": 2128, + "endOffset": 2131, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.1", + "startOffset": 2141, + "endOffset": 2144, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.2", + "startOffset": 2184, + "endOffset": 2187, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2188, + "endOffset": 2189, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2190, + "endOffset": 2191, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2192, + "endOffset": 2193, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.1", + "startOffset": 2261, + "endOffset": 2264, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "physicochemical", + "startOffset": 2265, + "endOffset": 2280, + "type": "Skill", + "confidence": 0.68 + }, + { + "value": "characteristics", + "startOffset": 2281, + "endOffset": 2296, + "type": "Skill", + "confidence": 0.5 + }, + { + "value": "2", + "startOffset": 2297, + "endOffset": 2298, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2299, + "endOffset": 2300, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2301, + "endOffset": 2302, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2327, + "endOffset": 2328, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2", + "startOffset": 2355, + "endOffset": 2358, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.3", + "startOffset": 2367, + "endOffset": 2370, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2462, + "endOffset": 2463, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2464, + "endOffset": 2465, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 2466, + "endOffset": 2467, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.1", + "startOffset": 2491, + "endOffset": 2494, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2495, + "endOffset": 2496, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2497, + "endOffset": 2498, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "5", + "startOffset": 2499, + "endOffset": 2500, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.4", + "startOffset": 2571, + "endOffset": 2574, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1.5", + "startOffset": 2583, + "endOffset": 2586, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2587, + "endOffset": 2588, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2589, + "endOffset": 2590, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 2591, + "endOffset": 2592, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.5", + "startOffset": 2638, + "endOffset": 2641, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2653, + "endOffset": 2654, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2655, + "endOffset": 2656, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2657, + "endOffset": 2658, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 2659, + "endOffset": 2660, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.6", + "startOffset": 2723, + "endOffset": 2726, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2735, + "endOffset": 2736, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 2781, + "endOffset": 2790, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "one", + "startOffset": 2876, + "endOffset": 2879, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2900, + "endOffset": 2901, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2902, + "endOffset": 2903, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "8", + "startOffset": 2904, + "endOffset": 2905, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.7", + "startOffset": 2962, + "endOffset": 2965, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.9.1", + "startOffset": 2966, + "endOffset": 2973, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "Toxicokinetics", + "startOffset": 2974, + "endOffset": 2988, + "type": "Skill", + "confidence": 0.57 + }, + { + "value": "3.9", + "startOffset": 2989, + "endOffset": 2992, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.1", + "startOffset": 3001, + "endOffset": 3004, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.9.2", + "startOffset": 3005, + "endOffset": 3012, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "3.11", + "startOffset": 3033, + "endOffset": 3037, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.3", + "startOffset": 3046, + "endOffset": 3049, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.9.3", + "startOffset": 3050, + "endOffset": 3057, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "3.10", + "startOffset": 3071, + "endOffset": 3075, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.2", + "startOffset": 3084, + "endOffset": 3087, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.9.4", + "startOffset": 3088, + "endOffset": 3095, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "3.12", + "startOffset": 3133, + "endOffset": 3137, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.3", + "startOffset": 3146, + "endOffset": 3149, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.3": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "+44 (0)1252 392460", + "startOffset": 139, + "endOffset": 157, + "type": "PhoneNumber", + "confidence": 0.8 + }, + { + "value": "regulatedproducts.submissions@intertek.com", + "startOffset": 165, + "endOffset": 207, + "type": "Email", + "confidence": 0.8 + }, + { + "value": "Sciences", + "startOffset": 237, + "endOffset": 245, + "type": "Organization", + "confidence": 0.78 + }, + { + "value": "1068", + "startOffset": 277, + "endOffset": 281, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Building A8 Ively Road, Farnborough Hampshire GU14 0LX United", + "startOffset": 283, + "endOffset": 344, + "type": "Address", + "confidence": 0.71 + }, + { + "value": "United Kingdom", + "startOffset": 338, + "endOffset": 352, + "type": "Location", + "confidence": 0.89 + } + ], + "2.1.4": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "01", + "startOffset": 23, + "endOffset": 25, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2024", + "startOffset": 32, + "endOffset": 36, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.1": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Smith Corporation", + "startOffset": 67, + "endOffset": 84, + "type": "Organization", + "confidence": 0.88 + }, + { + "value": "Buckingham Palace Road London SW1A 1AA", + "startOffset": 103, + "endOffset": 141, + "type": "Address", + "confidence": 0.9 + }, + { + "value": "John Smith", + "startOffset": 158, + "endOffset": 168, + "type": "Person", + "confidence": 0.98 + }, + { + "value": "Manager", + "startOffset": 185, + "endOffset": 192, + "type": "PersonType", + "confidence": 0.7 + }, + { + "value": "01234 56789", + "startOffset": 227, + "endOffset": 238, + "type": "PhoneNumber", + "confidence": 0.8 + }, + { + "value": "john.smith@smithcorp.com", + "startOffset": 246, + "endOffset": 270, + "type": "Email", + "confidence": 0.8 + } + ], + "2.1.2": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Smith Corporation", + "startOffset": 73, + "endOffset": 90, + "type": "Organization", + "confidence": 0.84 + }, + { + "value": "Buckingham Palace Buckingham Palace Road London SW1A", + "startOffset": 91, + "endOffset": 143, + "type": "Address", + "confidence": 0.78 + }, + { + "value": "Mimi Lang", + "startOffset": 164, + "endOffset": 173, + "type": "Person", + "confidence": 0.81 + }, + { + "value": "01223 45678", + "startOffset": 224, + "endOffset": 235, + "type": "PhoneNumber", + "confidence": 0.8 + }, + { + "value": "mimi.lang@smithcorp.com", + "startOffset": 243, + "endOffset": 266, + "type": "Email", + "confidence": 0.8 + } + ], + "0": [ + { + "value": "CASSIA GUM", + "startOffset": 16, + "endOffset": 26, + "type": "Product", + "confidence": 0.8 + }, + { + "value": "EUROPEAN UNION", + "startOffset": 53, + "endOffset": 67, + "type": "Organization", + "confidence": 0.72 + }, + { + "value": "1333/2008", + "startOffset": 99, + "endOffset": 108, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 116, + "endOffset": 135, + "type": "Organization", + "confidence": 0.98 + }, + { + "value": "Council", + "startOffset": 147, + "endOffset": 154, + "type": "Organization", + "confidence": 0.76 + }, + { + "value": "16 December 2008", + "startOffset": 158, + "endOffset": 174, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "Smith Corporation", + "startOffset": 238, + "endOffset": 255, + "type": "Organization", + "confidence": 0.99 + }, + { + "value": "Buckingham Palace Buckingham", + "startOffset": 256, + "endOffset": 284, + "type": "Location", + "confidence": 0.78 + }, + { + "value": "Buckingham Palace Road London", + "startOffset": 274, + "endOffset": 303, + "type": "Address", + "confidence": 0.6 + }, + { + "value": "01 August, 2024", + "startOffset": 330, + "endOffset": 345, + "type": "DateTime", + "confidence": 0.83 + } + ], + "1": [ + { + "value": "Cassia Gum", + "startOffset": 16, + "endOffset": 26, + "type": "Product", + "confidence": 0.89 + } + ], + "2.1.9": [ + { + "value": "1", + "startOffset": 0, + "endOffset": 1, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 42, + "endOffset": 43, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 64, + "endOffset": 65, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 120, + "endOffset": 121, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 179, + "endOffset": 180, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 275, + "endOffset": 276, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 298, + "endOffset": 299, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 332, + "endOffset": 333, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 368, + "endOffset": 369, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1829/2003", + "startOffset": 427, + "endOffset": 436, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 475, + "endOffset": 476, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 512, + "endOffset": 513, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 545, + "endOffset": 546, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 612, + "endOffset": 613, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Studies", + "startOffset": 628, + "endOffset": 635, + "type": "Skill", + "confidence": 0.61 + }, + { + "value": "Application", + "startOffset": 661, + "endOffset": 672, + "type": "Skill", + "confidence": 0.88 + }, + { + "value": "2", + "startOffset": 678, + "endOffset": 679, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.1", + "startOffset": 747, + "endOffset": 750, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2", + "startOffset": 789, + "endOffset": 792, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 842, + "endOffset": 843, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 844, + "endOffset": 845, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 846, + "endOffset": 847, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 892, + "endOffset": 893, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 894, + "endOffset": 895, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 896, + "endOffset": 897, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 928, + "endOffset": 929, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 930, + "endOffset": 931, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 932, + "endOffset": 933, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Specifications", + "startOffset": 934, + "endOffset": 948, + "type": "Skill", + "confidence": 0.55 + }, + { + "value": "Batch Analysis", + "startOffset": 953, + "endOffset": 967, + "type": "Skill", + "confidence": 1.0 + }, + { + "value": "3", + "startOffset": 973, + "endOffset": 974, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.1", + "startOffset": 991, + "endOffset": 994, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1088, + "endOffset": 1089, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1090, + "endOffset": 1091, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1092, + "endOffset": 1093, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Batch Analysis", + "startOffset": 1094, + "endOffset": 1108, + "type": "Skill", + "confidence": 0.77 + }, + { + "value": "3", + "startOffset": 1109, + "endOffset": 1110, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1111, + "endOffset": 1112, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1113, + "endOffset": 1114, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Contaminants", + "startOffset": 1115, + "endOffset": 1127, + "type": "Skill", + "confidence": 0.53 + }, + { + "value": "3", + "startOffset": 1128, + "endOffset": 1129, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1130, + "endOffset": 1131, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1132, + "endOffset": 1133, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1234, + "endOffset": 1235, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1236, + "endOffset": 1237, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1238, + "endOffset": 1239, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2", + "startOffset": 1263, + "endOffset": 1266, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Manufacturing Process", + "startOffset": 1287, + "endOffset": 1308, + "type": "Skill", + "confidence": 0.98 + }, + { + "value": "3", + "startOffset": 1309, + "endOffset": 1310, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1311, + "endOffset": 1312, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1313, + "endOffset": 1314, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1343, + "endOffset": 1344, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1345, + "endOffset": 1346, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1347, + "endOffset": 1348, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Manufacturing Process", + "startOffset": 1373, + "endOffset": 1394, + "type": "Skill", + "confidence": 0.93 + }, + { + "value": "3", + "startOffset": 1410, + "endOffset": 1411, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1412, + "endOffset": 1413, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1414, + "endOffset": 1415, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Manufacturing Process", + "startOffset": 1439, + "endOffset": 1460, + "type": "Skill", + "confidence": 0.64 + }, + { + "value": "3.3", + "startOffset": 1461, + "endOffset": 1464, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1493, + "endOffset": 1494, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1495, + "endOffset": 1496, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1497, + "endOffset": 1498, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1555, + "endOffset": 1556, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1557, + "endOffset": 1558, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1559, + "endOffset": 1560, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.4", + "startOffset": 1597, + "endOffset": 1600, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1688, + "endOffset": 1689, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1690, + "endOffset": 1691, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1692, + "endOffset": 1693, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1718, + "endOffset": 1719, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1720, + "endOffset": 1721, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1722, + "endOffset": 1723, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.5", + "startOffset": 1783, + "endOffset": 1786, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1832, + "endOffset": 1833, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "5", + "startOffset": 1834, + "endOffset": 1835, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1836, + "endOffset": 1837, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.6", + "startOffset": 1849, + "endOffset": 1852, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1921, + "endOffset": 1922, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 1923, + "endOffset": 1924, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1925, + "endOffset": 1926, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 1945, + "endOffset": 1946, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 1947, + "endOffset": 1948, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 1949, + "endOffset": 1950, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.7", + "startOffset": 1980, + "endOffset": 1983, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2040, + "endOffset": 2041, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 2042, + "endOffset": 2043, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2044, + "endOffset": 2045, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2075, + "endOffset": 2076, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 2077, + "endOffset": 2078, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 2079, + "endOffset": 2080, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2113, + "endOffset": 2114, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 2115, + "endOffset": 2116, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2117, + "endOffset": 2118, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.8", + "startOffset": 2162, + "endOffset": 2165, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Safety Evaluation", + "startOffset": 2166, + "endOffset": 2183, + "type": "Skill", + "confidence": 0.75 + }, + { + "value": "3.9", + "startOffset": 2228, + "endOffset": 2231, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2304, + "endOffset": 2305, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "9", + "startOffset": 2306, + "endOffset": 2307, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2308, + "endOffset": 2309, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.10", + "startOffset": 2334, + "endOffset": 2338, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 2352, + "endOffset": 2353, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10", + "startOffset": 2354, + "endOffset": 2356, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2357, + "endOffset": 2358, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 2409, + "endOffset": 2410, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.11", + "startOffset": 2412, + "endOffset": 2416, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.12", + "startOffset": 2460, + "endOffset": 2464, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.13", + "startOffset": 2502, + "endOffset": 2506, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.14", + "startOffset": 2547, + "endOffset": 2551, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.15", + "startOffset": 2566, + "endOffset": 2570, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.16", + "startOffset": 2642, + "endOffset": 2646, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 2706, + "endOffset": 2707, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.1", + "startOffset": 2724, + "endOffset": 2727, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.2", + "startOffset": 2760, + "endOffset": 2763, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.3", + "startOffset": 2844, + "endOffset": 2847, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Consumer", + "startOffset": 2880, + "endOffset": 2888, + "type": "PersonType", + "confidence": 0.97 + }, + { + "value": "4.4", + "startOffset": 2889, + "endOffset": 2892, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Consumer", + "startOffset": 2942, + "endOffset": 2950, + "type": "PersonType", + "confidence": 0.96 + }, + { + "value": "4.5", + "startOffset": 2951, + "endOffset": 2954, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.6", + "startOffset": 3023, + "endOffset": 3026, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.7", + "startOffset": 3055, + "endOffset": 3058, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.8", + "startOffset": 3113, + "endOffset": 3116, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Analytical", + "startOffset": 3117, + "endOffset": 3127, + "type": "Skill", + "confidence": 0.56 + }, + { + "value": "4.9", + "startOffset": 3223, + "endOffset": 3226, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 3313, + "endOffset": 3322, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4.10", + "startOffset": 3323, + "endOffset": 3327, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 3411, + "endOffset": 3420, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 3486, + "endOffset": 3487, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3488, + "endOffset": 3489, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 3490, + "endOffset": 3491, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3492, + "endOffset": 3493, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 3551, + "endOffset": 3552, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 3580, + "endOffset": 3581, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3582, + "endOffset": 3583, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 3584, + "endOffset": 3585, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 3586, + "endOffset": 3587, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cagate", + "startOffset": 3626, + "endOffset": 3632, + "type": "Skill", + "confidence": 0.5 + }, + { + "value": "2", + "startOffset": 3641, + "endOffset": 3642, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2.2.2", + "startOffset": 3670, + "endOffset": 3677, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3678, + "endOffset": 3679, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Manufacturing", + "startOffset": 3680, + "endOffset": 3693, + "type": "Skill", + "confidence": 0.72 + }, + { + "value": "3", + "startOffset": 3742, + "endOffset": 3743, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 3744, + "endOffset": 3745, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 3746, + "endOffset": 3747, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3748, + "endOffset": 3749, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "0.8", + "startOffset": 3782, + "endOffset": 3785, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "168", + "startOffset": 3803, + "endOffset": 3806, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3833, + "endOffset": 3834, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3837, + "endOffset": 3838, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3885, + "endOffset": 3886, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 3889, + "endOffset": 3890, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3937, + "endOffset": 3938, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3941, + "endOffset": 3942, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 3978, + "endOffset": 3979, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 3982, + "endOffset": 3983, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EU", + "startOffset": 4044, + "endOffset": 4046, + "type": "Organization", + "confidence": 0.49 + }, + { + "value": "234/2011", + "startOffset": 4051, + "endOffset": 4059, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1331/2008", + "startOffset": 4081, + "endOffset": 4090, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EFSA", + "startOffset": 4101, + "endOffset": 4105, + "type": "Organization", + "confidence": 0.96 + }, + { + "value": "EFSA", + "startOffset": 4161, + "endOffset": 4165, + "type": "Organization", + "confidence": 0.93 + }, + { + "value": "ANS", + "startOffset": 4166, + "endOffset": 4169, + "type": "Organization", + "confidence": 0.47 + }, + { + "value": "2021", + "startOffset": 4177, + "endOffset": 4181, + "type": "DateTime", + "confidence": 0.97 + }, + { + "value": "1", + "startOffset": 4189, + "endOffset": 4190, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4193, + "endOffset": 4194, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.1", + "startOffset": 4245, + "endOffset": 4248, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4249, + "endOffset": 4250, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4295, + "endOffset": 4296, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4297, + "endOffset": 4298, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4299, + "endOffset": 4300, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4301, + "endOffset": 4302, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.2.1", + "startOffset": 4347, + "endOffset": 4354, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4355, + "endOffset": 4356, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2.2.2.1", + "startOffset": 4403, + "endOffset": 4410, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4411, + "endOffset": 4412, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia Gum", + "startOffset": 4427, + "endOffset": 4437, + "type": "Product", + "confidence": 0.73 + }, + { + "value": "2", + "startOffset": 4459, + "endOffset": 4460, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4461, + "endOffset": 4462, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 4463, + "endOffset": 4464, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4465, + "endOffset": 4466, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia Gum", + "startOffset": 4486, + "endOffset": 4496, + "type": "Product", + "confidence": 0.96 + }, + { + "value": "2", + "startOffset": 4503, + "endOffset": 4504, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4505, + "endOffset": 4506, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 4507, + "endOffset": 4508, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4509, + "endOffset": 4510, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia Gum", + "startOffset": 4530, + "endOffset": 4540, + "type": "Product", + "confidence": 0.86 + }, + { + "value": "3", + "startOffset": 4547, + "endOffset": 4548, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4549, + "endOffset": 4550, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4551, + "endOffset": 4552, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4553, + "endOffset": 4554, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Batch Analysis", + "startOffset": 4555, + "endOffset": 4569, + "type": "Skill", + "confidence": 0.94 + }, + { + "value": "16", + "startOffset": 4574, + "endOffset": 4576, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia", + "startOffset": 4588, + "endOffset": 4594, + "type": "Product", + "confidence": 0.63 + }, + { + "value": "3.1.2.1", + "startOffset": 4605, + "endOffset": 4612, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4613, + "endOffset": 4614, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Heavy Metal Analysis", + "startOffset": 4615, + "endOffset": 4635, + "type": "Skill", + "confidence": 0.89 + }, + { + "value": "21", + "startOffset": 4640, + "endOffset": 4642, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia", + "startOffset": 4654, + "endOffset": 4660, + "type": "Product", + "confidence": 0.74 + }, + { + "value": "3.1.2.2", + "startOffset": 4671, + "endOffset": 4678, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4679, + "endOffset": 4680, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Analysis", + "startOffset": 4681, + "endOffset": 4689, + "type": "Skill", + "confidence": 0.6 + }, + { + "value": "Residual", + "startOffset": 4694, + "endOffset": 4702, + "type": "Skill", + "confidence": 0.52 + }, + { + "value": "16", + "startOffset": 4715, + "endOffset": 4717, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.1.2.3", + "startOffset": 4746, + "endOffset": 4753, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4754, + "endOffset": 4755, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Microbial Analysis", + "startOffset": 4756, + "endOffset": 4774, + "type": "Skill", + "confidence": 0.97 + }, + { + "value": "16", + "startOffset": 4779, + "endOffset": 4781, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 4810, + "endOffset": 4811, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4812, + "endOffset": 4813, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 4814, + "endOffset": 4815, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4816, + "endOffset": 4817, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 4844, + "endOffset": 4845, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 4888, + "endOffset": 4889, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 4890, + "endOffset": 4891, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4892, + "endOffset": 4893, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4894, + "endOffset": 4895, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2.2.1", + "startOffset": 4940, + "endOffset": 4947, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 4948, + "endOffset": 4949, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.2.2.2", + "startOffset": 5016, + "endOffset": 5023, + "type": "IPAddress", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5024, + "endOffset": 5025, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5110, + "endOffset": 5111, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 5112, + "endOffset": 5113, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5114, + "endOffset": 5115, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5116, + "endOffset": 5117, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5148, + "endOffset": 5149, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 5150, + "endOffset": 5151, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5152, + "endOffset": 5153, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5154, + "endOffset": 5155, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "0.8", + "startOffset": 5188, + "endOffset": 5191, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": ".8%", + "startOffset": 5189, + "endOffset": 5192, + "type": "Quantity", + "confidence": 0.89 + }, + { + "value": "168", + "startOffset": 5209, + "endOffset": 5212, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5239, + "endOffset": 5240, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 5241, + "endOffset": 5242, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5243, + "endOffset": 5244, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5245, + "endOffset": 5246, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5331, + "endOffset": 5332, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 5333, + "endOffset": 5334, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5335, + "endOffset": 5336, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5337, + "endOffset": 5338, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Union", + "startOffset": 5464, + "endOffset": 5478, + "type": "Organization", + "confidence": 0.69 + }, + { + "value": "3", + "startOffset": 5485, + "endOffset": 5486, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 5487, + "endOffset": 5488, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5489, + "endOffset": 5490, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5491, + "endOffset": 5492, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3.9", + "startOffset": 5673, + "endOffset": 5676, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5677, + "endOffset": 5678, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 5754, + "endOffset": 5755, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "5", + "startOffset": 5756, + "endOffset": 5757, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5758, + "endOffset": 5759, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 5760, + "endOffset": 5761, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5846, + "endOffset": 5847, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "6", + "startOffset": 5848, + "endOffset": 5849, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 5850, + "endOffset": 5851, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "3", + "startOffset": 5852, + "endOffset": 5853, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia Gum", + "startOffset": 5969, + "endOffset": 5979, + "type": "Product", + "confidence": 0.95 + } + ], + "2.1.6.5": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "2", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia Gum", + "startOffset": 26, + "endOffset": 36, + "type": "Product", + "confidence": 0.99 + } + ], + "2.1.6.6": [ + { + "value": "Cassia Gum", + "startOffset": 0, + "endOffset": 10, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "Xanthan Gum", + "startOffset": 11, + "endOffset": 22, + "type": "Product", + "confidence": 0.94 + } + ], + "2.1.6.3": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.6.4": [ + { + "value": "400 to 6,000 kDa", + "startOffset": 48, + "endOffset": 64, + "type": "Quantity", + "confidence": 0.84 + }, + { + "value": "Gidley", + "startOffset": 66, + "endOffset": 72, + "type": "Person", + "confidence": 0.95 + }, + { + "value": "1991", + "startOffset": 81, + "endOffset": 85, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "Lang", + "startOffset": 87, + "endOffset": 91, + "type": "Person", + "confidence": 0.85 + }, + { + "value": "Kajiwara", + "startOffset": 96, + "endOffset": 104, + "type": "Person", + "confidence": 0.78 + }, + { + "value": "1993", + "startOffset": 106, + "endOffset": 110, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "Kato", + "startOffset": 112, + "endOffset": 116, + "type": "Person", + "confidence": 0.83 + }, + { + "value": "2000", + "startOffset": 118, + "endOffset": 122, + "type": "DateTime", + "confidence": 0.96 + }, + { + "value": "2001", + "startOffset": 165, + "endOffset": 169, + "type": "DateTime", + "confidence": 0.95 + }, + { + "value": "JECFA", + "startOffset": 171, + "endOffset": 176, + "type": "Organization", + "confidence": 0.63 + }, + { + "value": "2017", + "startOffset": 178, + "endOffset": 182, + "type": "DateTime", + "confidence": 0.97 + }, + { + "value": "2023", + "startOffset": 197, + "endOffset": 201, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "Cassia", + "startOffset": 419, + "endOffset": 425, + "type": "Product", + "confidence": 0.58 + }, + { + "value": "(75°C", + "startOffset": 614, + "endOffset": 619, + "type": "Quantity", + "confidence": 1.0 + }, + { + "value": "insoluble", + "startOffset": 622, + "endOffset": 631, + "type": "Skill", + "confidence": 0.53 + }, + { + "value": "ethanol", + "startOffset": 635, + "endOffset": 642, + "type": "Product", + "confidence": 0.89 + }, + { + "value": "organic solvents", + "startOffset": 653, + "endOffset": 669, + "type": "Product", + "confidence": 0.72 + }, + { + "value": "solvents", + "startOffset": 683, + "endOffset": 691, + "type": "Product", + "confidence": 0.49 + }, + { + "value": "3.1", + "startOffset": 729, + "endOffset": 732, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "EC", + "startOffset": 780, + "endOffset": 782, + "type": "Organization", + "confidence": 0.71 + }, + { + "value": "European Commission", + "startOffset": 785, + "endOffset": 804, + "type": "Organization", + "confidence": 0.98 + }, + { + "value": "EINECS", + "startOffset": 806, + "endOffset": 812, + "type": "Organization", + "confidence": 0.58 + }, + { + "value": "IUPAC", + "startOffset": 878, + "endOffset": 883, + "type": "Organization", + "confidence": 0.95 + }, + { + "value": "International Union of Pure and Applied Chemistry", + "startOffset": 886, + "endOffset": 935, + "type": "Organization", + "confidence": 0.96 + }, + { + "value": "Cassia gum", + "startOffset": 957, + "endOffset": 967, + "type": "Product", + "confidence": 0.92 + }, + { + "value": "cassia gum", + "startOffset": 1173, + "endOffset": 1183, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "5", + "startOffset": 1204, + "endOffset": 1205, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1206, + "endOffset": 1207, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "processing", + "startOffset": 1255, + "endOffset": 1265, + "type": "Skill", + "confidence": 0.87 + }, + { + "value": "Mannose", + "startOffset": 1275, + "endOffset": 1282, + "type": "Product", + "confidence": 0.58 + }, + { + "value": "polymer", + "startOffset": 1334, + "endOffset": 1341, + "type": "Product", + "confidence": 0.79 + }, + { + "value": "Mannose", + "startOffset": 1343, + "endOffset": 1350, + "type": "Product", + "confidence": 0.64 + }, + { + "value": "1,4", + "startOffset": 1373, + "endOffset": 1376, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1,6", + "startOffset": 1464, + "endOffset": 1467, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "10-12%", + "startOffset": 1524, + "endOffset": 1530, + "type": "Quantity", + "confidence": 0.97 + }, + { + "value": "5%", + "startOffset": 1579, + "endOffset": 1581, + "type": "Quantity", + "confidence": 0.99 + } + ], + "2.1.6.1": [ + { + "value": "application", + "startOffset": 5, + "endOffset": 16, + "type": "Skill", + "confidence": 0.74 + }, + { + "value": "cassia gum", + "startOffset": 45, + "endOffset": 55, + "type": "Product", + "confidence": 0.98 + }, + { + "value": "additive", + "startOffset": 74, + "endOffset": 82, + "type": "Product", + "confidence": 0.56 + }, + { + "value": "EU", + "startOffset": 90, + "endOffset": 92, + "type": "Organization", + "confidence": 0.93 + }, + { + "value": "1333/2008", + "startOffset": 118, + "endOffset": 127, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia gum", + "startOffset": 129, + "endOffset": 139, + "type": "Product", + "confidence": 0.97 + }, + { + "value": "polysaccharides", + "startOffset": 214, + "endOffset": 229, + "type": "Product", + "confidence": 0.6 + }, + { + "value": "EU", + "startOffset": 263, + "endOffset": 265, + "type": "Organization", + "confidence": 0.84 + }, + { + "value": "xanthan gum", + "startOffset": 275, + "endOffset": 286, + "type": "Product", + "confidence": 0.98 + }, + { + "value": "locust bean gum", + "startOffset": 295, + "endOffset": 310, + "type": "Product", + "confidence": 0.95 + }, + { + "value": "guar gum", + "startOffset": 323, + "endOffset": 331, + "type": "Product", + "confidence": 0.96 + }, + { + "value": "emulsifying", + "startOffset": 346, + "endOffset": 357, + "type": "Skill", + "confidence": 0.9 + }, + { + "value": "gelling", + "startOffset": 359, + "endOffset": 366, + "type": "Skill", + "confidence": 0.57 + }, + { + "value": "3.6", + "startOffset": 466, + "endOffset": 469, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia gum", + "startOffset": 472, + "endOffset": 482, + "type": "Product", + "confidence": 0.89 + }, + { + "value": "6", + "startOffset": 505, + "endOffset": 506, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 529, + "endOffset": 538, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia gum", + "startOffset": 551, + "endOffset": 561, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "Cassia tora", + "startOffset": 563, + "endOffset": 574, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "Cassia obtusifolia", + "startOffset": 578, + "endOffset": 596, + "type": "Product", + "confidence": 0.99 + }, + { + "value": "seeds", + "startOffset": 627, + "endOffset": 632, + "type": "Product", + "confidence": 0.61 + }, + { + "value": "seeds", + "startOffset": 649, + "endOffset": 654, + "type": "Product", + "confidence": 0.98 + }, + { + "value": "grinding", + "startOffset": 722, + "endOffset": 730, + "type": "Skill", + "confidence": 0.74 + }, + { + "value": "medium", + "startOffset": 803, + "endOffset": 809, + "type": "Product", + "confidence": 0.92 + }, + { + "value": "packaged", + "startOffset": 845, + "endOffset": 853, + "type": "Skill", + "confidence": 0.93 + }, + { + "value": "Cassia gum", + "startOffset": 894, + "endOffset": 904, + "type": "Product", + "confidence": 1.0 + }, + { + "value": "natural", + "startOffset": 910, + "endOffset": 917, + "type": "Product", + "confidence": 0.6 + }, + { + "value": "food additive", + "startOffset": 918, + "endOffset": 931, + "type": "Product", + "confidence": 0.61 + }, + { + "value": "Cassia tora", + "startOffset": 979, + "endOffset": 990, + "type": "Product", + "confidence": 0.92 + }, + { + "value": "Cassia obtusifolia", + "startOffset": 995, + "endOffset": 1013, + "type": "Product", + "confidence": 0.69 + }, + { + "value": "legume", + "startOffset": 1042, + "endOffset": 1048, + "type": "Product", + "confidence": 0.77 + }, + { + "value": "food products", + "startOffset": 1137, + "endOffset": 1150, + "type": "Product", + "confidence": 0.93 + }, + { + "value": "1", + "startOffset": 1267, + "endOffset": 1268, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1269, + "endOffset": 1270, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "4", + "startOffset": 1271, + "endOffset": 1272, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Food Safety Authority", + "startOffset": 1280, + "endOffset": 1310, + "type": "Organization", + "confidence": 0.99 + }, + { + "value": "EFSA", + "startOffset": 1312, + "endOffset": 1316, + "type": "Organization", + "confidence": 0.95 + }, + { + "value": "food additive", + "startOffset": 1346, + "endOffset": 1359, + "type": "Product", + "confidence": 0.56 + }, + { + "value": "EFSA ANS Panel", + "startOffset": 1373, + "endOffset": 1387, + "type": "Organization", + "confidence": 0.84 + }, + { + "value": "2021", + "startOffset": 1389, + "endOffset": 1393, + "type": "DateTime", + "confidence": 0.99 + }, + { + "value": "1", + "startOffset": 1422, + "endOffset": 1423, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 1426, + "endOffset": 1427, + "type": "Quantity", + "confidence": 0.8 + } + ], + "2.1.6.2": [ + { + "value": "1", + "startOffset": 6, + "endOffset": 7, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1", + "startOffset": 10, + "endOffset": 11, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "12345", + "startOffset": 105, + "endOffset": 110, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "67", + "startOffset": 111, + "endOffset": 113, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "8", + "startOffset": 114, + "endOffset": 115, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "123", + "startOffset": 140, + "endOffset": 143, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "456", + "startOffset": 144, + "endOffset": 147, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "7", + "startOffset": 148, + "endOffset": 149, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "Cassia tora gum", + "startOffset": 173, + "endOffset": 188, + "type": "Product", + "confidence": 0.8 + }, + { + "value": "cassia powder", + "startOffset": 213, + "endOffset": 226, + "type": "Product", + "confidence": 1.0 + }, + { + "value": "cassia polysaccharide", + "startOffset": 228, + "endOffset": 249, + "type": "Product", + "confidence": 0.83 + }, + { + "value": "cassia seed extract", + "startOffset": 280, + "endOffset": 299, + "type": "Product", + "confidence": 0.81 + }, + { + "value": "1", + "startOffset": 300, + "endOffset": 301, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "1333/2008", + "startOffset": 321, + "endOffset": 330, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "European Parliament", + "startOffset": 338, + "endOffset": 357, + "type": "Organization", + "confidence": 1.0 + }, + { + "value": "Council", + "startOffset": 369, + "endOffset": 376, + "type": "Organization", + "confidence": 0.7 + }, + { + "value": "16 December 2008", + "startOffset": 380, + "endOffset": 396, + "type": "DateTime", + "confidence": 1.0 + }, + { + "value": "354", + "startOffset": 421, + "endOffset": 424, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "31.12.2008", + "startOffset": 426, + "endOffset": 436, + "type": "DateTime", + "confidence": 0.98 + }, + { + "value": "16", + "startOffset": 441, + "endOffset": 443, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "–", + "startOffset": 443, + "endOffset": 444, + "type": "Quantity", + "confidence": 0.51 + }, + { + "value": "33", + "startOffset": 444, + "endOffset": 446, + "type": "Quantity", + "confidence": 0.8 + }, + { + "value": "http://eur-lex.europa.eu/legalcontent/EN/ALL/?uri=CELEX:32008R1333&qid=1437074262608", + "startOffset": 466, + "endOffset": 550, + "type": "URL", + "confidence": 0.8 + }, + { + "value": "23/12/2020", + "startOffset": 582, + "endOffset": 592, + "type": "DateTime", + "confidence": 1.0 + } + ] + } +} \ No newline at end of file diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.NER_ENTITIES.json b/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.NER_ENTITIES.json new file mode 100644 index 00000000..ab2ce425 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/test/resources/ner_entities/intertek.NER_ENTITIES.json @@ -0,0 +1 @@ +{"dossierId": "2e41b84e-30ed-4098-b722-ed309a8a5bfb", "fileId": "caf8ba677d05df7a6625449e43c20baf", "targetFileExtension": "SIMPLIFIED_TEXT.json.gz", "responseFileExtension": "NER_ENTITIES.json.gz", "X-TENANT-ID": "redaction", "data": {"2.1.1": [{"value": "Corporation Buckingham Palace Buckingham Palace Road", "startOffset": 73, "endOffset": 125, "type": "DEPARTMENT"}, {"value": "Head of Alliance Management", "startOffset": 194, "endOffset": 221, "type": "JOB_TITEL"}, {"value": "john.smith@smithcorp.com", "startOffset": 246, "endOffset": 270, "type": "MAIL"}], "2.1.2": [{"value": "Corporation Buckingham Palace Buckingham Palace Road", "startOffset": 79, "endOffset": 131, "type": "DEPARTMENT"}, {"value": "Head of Manufacture Tel", "startOffset": 199, "endOffset": 222, "type": "JOB_TITEL"}, {"value": "mimi.lang@smithcorp.com", "startOffset": 243, "endOffset": 266, "type": "MAIL"}], "2.1.3": [{"value": "+44 (0)1252 392460 Email:", "startOffset": 139, "endOffset": 164, "type": "PHONE"}, {"value": "United Kingdom", "startOffset": 338, "endOffset": 352, "type": "COUNTRY"}], "2.1.6.1": [{"value": "EU", "startOffset": 90, "endOffset": 92, "type": "ORG"}, {"value": "EU", "startOffset": 263, "endOffset": 265, "type": "ORG"}, {"value": "European Food Safety Authority", "startOffset": 1280, "endOffset": 1310, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 1373, "endOffset": 1387, "type": "ORG"}], "2.1.6.4": [{"value": "Gidley", "startOffset": 66, "endOffset": 72, "type": "CBI_author"}, {"value": "Dentini", "startOffset": 149, "endOffset": 156, "type": "CBI_author"}, {"value": "Lang", "startOffset": 87, "endOffset": 91, "type": "CBI_author"}, {"value": "Kajiwara", "startOffset": 96, "endOffset": 104, "type": "CBI_author"}, {"value": "Kato", "startOffset": 112, "endOffset": 116, "type": "CBI_author"}, {"value": "Lang", "startOffset": 184, "endOffset": 188, "type": "CBI_author"}], "2.1.9": [{"value": "EFSA", "startOffset": 4101, "endOffset": 4105, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 4161, "endOffset": 4175, "type": "ORG"}, {"value": "Ames", "startOffset": 2392, "endOffset": 2396, "type": "NO_AUTHOR"}], "2.1.10.2": [{"value": "EFSA", "startOffset": 942, "endOffset": 946, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 1002, "endOffset": 1016, "type": "ORG"}, {"value": "EFSA", "startOffset": 1101, "endOffset": 1105, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 1161, "endOffset": 1175, "type": "ORG"}, {"value": "EFSA", "startOffset": 1788, "endOffset": 1792, "type": "ORG"}], "2.1.10.3": [{"value": "EFSA", "startOffset": 129, "endOffset": 133, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 189, "endOffset": 203, "type": "ORG"}], "2.1.10.4": [{"value": "EFSA", "startOffset": 129, "endOffset": 133, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 189, "endOffset": 203, "type": "ORG"}, {"value": "EFSA", "startOffset": 2618, "endOffset": 2622, "type": "ORG"}, {"value": "European Food Safety Authority", "startOffset": 2625, "endOffset": 2655, "type": "ORG"}, {"value": "European Food Safety Authority", "startOffset": 3893, "endOffset": 3923, "type": "ORG"}], "2.1.10.5": [{"value": "EFSA", "startOffset": 129, "endOffset": 133, "type": "ORG"}, {"value": "EFSA ANS Panel", "startOffset": 189, "endOffset": 203, "type": "ORG"}], "17": [{"value": "2", "startOffset": 18, "endOffset": 19, "type": "CARDINAL"}]}} \ No newline at end of file diff --git a/redaction-service-v1/rules-management/src/main/resources/all_redact_manager_rules.drl b/redaction-service-v1/rules-management/src/main/resources/all_redact_manager_rules.drl index 6e447a8e..27aea7cb 100644 --- a/redaction-service-v1/rules-management/src/main/resources/all_redact_manager_rules.drl +++ b/redaction-service-v1/rules-management/src/main/resources/all_redact_manager_rules.drl @@ -1734,6 +1734,88 @@ rule "AI.3.0: Recommend authors from AI as PII" .forEach(nerEntity -> entityCreationService.optionalByNerEntity(nerEntity, "PII", EntityType.RECOMMENDATION, document)); end + + + +// Rule unit: AI.4 +rule "AI.4.0: Add all NER Entities of type Person" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Person")) + then + nerEntities.streamEntitiesOfType("Person") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_author", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.4.0", ""))); + end + + +// Rule unit: AI.5 +rule "AI.5.0: Combine and add NER Entities as CBI_address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location") || hasEntitiesOfType("Address")|| hasEntitiesOfType("Organization")) + then + entityCreationService + .combineNerEntitiesWithConfidence( + nerEntities, + "CBI_address", + EntityType.RECOMMENDATION, + document, + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "CITY"), + Set.of("Organization", + "Location", + "Address", + "ORG", + "STREET", + "POSTAL", + "COUNTRY", + "CARDINAL", + "CITY", + "STATE"), + 50, + 3, + 2, + 0.7) + .forEach(nerEntity -> nerEntity.skip("AI.5.0", "")); + end + + + +// Rule unit: AI.6 +rule "AI.6.0: Add all NER Entities of type Location" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Location")) + then + nerEntities.streamEntitiesOfType("Location") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.6.0", ""))); + end + + +// Rule unit: AI.7 +rule "AI.7.0: Add all NER Entities of type Address" + salience 999 + when + nerEntities: NerEntities(hasEntitiesOfType("Address")) + then + nerEntities.streamEntitiesOfType("Address") + .filter(entity -> entity.value().length() > 3) + .filter(entity -> entity.value().length() < 100) + .forEach(nerEntity -> entityCreationService.optionalByNerEntityWithConfidence(nerEntity, 0.7, "CBI_address", EntityType.RECOMMENDATION, document) + .ifPresent(e -> e.skip("AI.7.0", ""))); + end + + //------------------------------------ Manual redaction rules ------------------------------------ // Rule unit: MAN.0