근처에 있는 맛집 정보를 찾기 위해 두 개의 리뷰 사이트를 이용하는 상황을 가정해보겠습니다. 이 때 같은 식당이 두 번 표시되지 않도록 중복되는 항목을 병합(merge)해야 합니다. Bixby는 각 concept에 equivalence definition을 설정하여 이런 상황을 처리합니다.
실제 input은 복잡하고 정확성이 떨어질 수 있기 때문에 단순 비교만으로는 두 input이 동등한지를 판단하기가 어렵습니다. 예를 들어 서로 가까이 있는 두 지역은 같은 지역으로 처리하는 것이 좋을 수도 있고, 사소한 오타가 있거나 정식 명칭과는 약간 다른 사업체 이름도 허용해야 할 수 있습니다. 또한 복잡한 구조체에서는 equivalence가 사업체 이름 및 작성자 같은 구조체의 일부 property에 좌우될 수 있습니다.
이 부분을 처리하기 위해서는 equivalence
definition을 사용하여 동일한 concept의 두 인스턴스를 비교하는 방법을 지정하면 됩니다. 두 concept 인스턴스에 대해 함수에서 true
가 반환되면 이 둘은 하나의 인스턴스로 병합되어 표시되고, false
가 반환되면 서로 동일한 인스턴스로 간주되지 않습니다. 또한 정보가 누락되었거나 퍼지 매치(fuzzy match)가 정확도 임계값 미만의 value를 반환할 경우 함수에서 uncertain
이 반환될 수 있습니다. 한마디로, true
매치로 간주되는 value만 병합됩니다. 이 동작은 구조체를 비교할 때 수정할 수 있습니다.
아래에서 설명하는 equivalence 함수는 결과를 병합하는 용도로만 사용됩니다. 또한 NLU 시스템에서는 사용되지 않으며, 사용자 input과는 전혀 관계가 없습니다.
기본적으로 두 원시 타입(primitive) value는 서로 동일할 경우 true
로 매치되고, 그렇지 않은 경우 false
로 매치됩니다. equivalence 함수 fuzzy-string-equality
는 문자열에 대해 이 임계값을 완화합니다. 예를 들면 다음과 같습니다.
name (BusinessName) {
description (The name of a business.)
equivalence: fuzzy-string-equality {
true-tolerance (0.9)
uncertain-tolerance (0.7)
similarity-measure (Edit)
}
}
또한 fuzzy-numeric-equality
를 사용하여 부동 소수점 value(원시 타입(primitive type) decimal
)에 대한 허용 오차(tolerance)를 설정할 수 있습니다. 구문은 fuzzy-string-equality
와 동일합니다.
숫자가 아닌 concept에는 fuzzy-numeric-equality
를 사용할 수 없습니다.
원시 타입(primitive) equivalence에 대한 자세한 내용은 참조 문서에서 확인할 수 있습니다.
두 구조체(structure)를 비교하는 것은 좀 더 복잡합니다. 기본적으로 시스템은 모든 property를 하나씩 비교하며 필요한 경우 하위 property도 비교 대상이 됩니다. 각 비교에서는 해당 property에 사용 가능한 equivalence definition이 사용됩니다. property가 누락된 구조체를 비교하면 항상 uncertain
이 반환됩니다. 그리고 모든 property 비교에서 true
가 반환되는 경우에만 equivalence 함수가 true
를 반환합니다.
Concept 구조체의 일부로 equivalence를 정의하여 이 동작을 수정할 수 있습니다. 이를 위해 두 가지 원시 타입(primitive) 제약 조건과 세 가지 결합이 사용됩니다.
원시 타입(primitive) 제약 조건은 다음과 같습니다.
convertible-concepts
: 이 제약 조건에서는 두 concept 인스턴스를 서로 변환할 수 있는 경우 true를 반환합니다. 이것은 두 인스턴스가 모두 동일한 concept type을 갖거나 한 인스턴스가 나머지 하나의 하위 type인 경우에 동작합니다. 예를 들어, 식당은 사업체를 확장한 것이므로 사업체와 식당은 서로 변환 가능한 type입니다. 반면, 식당과 영화관은 서로 변환 가능한 type이 아닙니다. 둘 다 사업체를 확장하지만 서로 간에 상속(inheritance) 관계가 없기 때문입니다.
equivalent-values(propertyName)
: 이 제약 조건은 특정 property에 대해 equivalence 결과를 반환합니다. 아래 예에서는 사업체 비교에 사업체의 name
및 address
property가 사용됩니다.
다른 제약 조건의 결과의 합계를 반환하기 위해서는 다음과 같은 논리곱(conjunction)이 사용됩니다.
join { constraint1 constraint2 ... }
: 이것은 nested 제약 조건 전체에 대한 min
함수와 같습니다. nested 제약 조건이 하나라도 false
를 반환하면 결과가 false이고, nested 제약 조건이 하나라도 uncertain
을 반환하면 결과가 uncertain입니다. 마찬가지로, nested 제약 조건이 모두 true
를 반환하는 경우에만 결과가 true
입니다.
optimistic-join { constraint1 constraint2 ... }
: 이것은 uncertain
을 true
로 처리하여 join
의 동작을 수정합니다. nested 제약 조건이 모두 true
또는 uncertain
을 반환하면 true
를 반환하고 그렇지 않으면 false
를 반환합니다. 이 논리곱(conjunction)은 uncertain
을 반환하지 않습니다.
pessimistic-join { constraint1 constraint2 ... }
: 이것은 uncertain
을 false
로 처리하여 join
의 동작을 수정합니다. nested 제약 조건이 모두 true
를 반환하면 true
를 반환하고 그렇지 않으면 false
를 반환합니다. 이 논리곱(conjunction)은 uncertain
을 반환하지 않습니다.
다음은 equivalence definition의 몇 가지 예입니다.
structure (Business) {
property (address) {
type (viv.geo.Address)
}
// ... more properties ...
// Businesses get merged if their name and addresses match in a fuzzy
// way with an "uncertain" tolerance:
equivalence: optimistic-join {
convertible-concepts
equivalent-values (name)
equivalent-values (address)
}
}
Business
구조체에서는 변환 가능한 concept의 비교를 통해 사업체를 식당과 비교합니다. 각 인스턴스에 대해 이름과 주소만 비교하며, 낙관적(optimistic) 집계를 사용하므로 이름 및 주소 비교가 true
또는 uncertain
을 반환하는 경우 결과가 true
입니다.
이것은 uncertain
을 어떻게 사용하면 유용한지를 보여줍니다. 두 인스턴스를 직접 비교할 때는 그다지 유용하지 않아 보일 수 있지만 부모 concept 비교까지 확장할 수 있다는 점에 주목할 필요가 있습니다. 예를 들어 사업체 이름 비교에서 uncertain
을 반환하고 주소 비교에서 true
를 반환할 경우, Business concept에 낙관적 결합(optimistic join)이 지정되었으므로 결과가 true
가 됩니다.
structure (GeoPoint) {
property (latitude) {
type (geo.Latitude)
min (Required)
}
property (longitude) {
type (geo.Longitude)
min (Required)
}
// The confidence for a point will be true, false or uncertain
// depending on the specified location tolerances.
equivalence: join {
fuzzy-numeric-equality(latitude) {
true-tolerance(0.00005)
uncertain-tolerance(0.005)
}
fuzzy-numeric-equality(longitude) {
true-tolerance(0.00005)
uncertain-tolerance(0.005)
}
}
}
위의 구조체 GeoPoint
는 latitude
및 longitude
property를 사용하여 비교합니다. 두 property가 지정된 허용 오차(tolerance) 내에 있는 경우에만 두 지점이 동등한 것으로 간주됩니다. 두 property 비교 중 하나라도 false가 반환되면 두 지점이 동등하지 않은 것을 간주되며, 그 외의 경우에는 결과가 uncertain입니다.
특수한 경우이긴 하나, distance-equality
제약 조건을 사용하여 GeoPoint
property에 대한 equivalence 규칙을 정의할 수도 있습니다. 이 경우 두 지점 간 지리적 거리가 지정된 거리 이내에 있으면 true를 반환합니다. 이 예에서 centroid
property는 GeoPoint이며, 두 중심점 간 거리가 0.2마일 이하이면 비교 결과 true가 반환됩니다.
equivalence: join {
distance-equality (centroid) {
unit (Miles)
magnitude (0.2)
}
}
viv.core.BaseGeoPoint
concept은 distance-equality
와 함께 사용해야 합니다.
구조체 equivalence에 대한 자세한 내용은 참조 문서에서 확인할 수 있습니다.
기본적으로 Bixby는 중복된 value를 병합하여 max (Many)
개수 제한규칙(cardinality)을 갖는 노드에 고유한 요소만 포함되도록 합니다. 예를 들어 Item
구조체(structure) concept을 가정해보겠습니다.
structure (Item) {
property (name) {
type (Name)
min (Required) max (One)
}
property (departments) {
type (Department)
min (Required) max (Many)
}
}
여기서 departments
property는 여러 Department
value를 포함할 수 있지만 각각의 value는 서로 중복될 수 없습니다. departments
에 ["Hardware", "Toys", "Home Goods"]
value가 있다고 할 때, "Kitchen"
이라는 value는 그대로 추가할 수 있지만 "Toys"
value를 추가할 경우에는 기존 "Toys"
value와 자동으로 병합되고 해당 value는 고유하게 유지됩니다.
이 동작은 no-auto-property-value-merging
플래그를 사용하여 오버라이딩할 수 있습니다. 이 오버라이딩이 설정되면 Bixby에서 multi-value 노드에 동일한 value를 두 번 이상 포함할 수 있습니다. Expression Language 함수 dedupe
을 사용하여 지정된 노드의 equivalence 요소를 병합할 수 있습니다. 예를 들어, 다음 action은 여러 문자열이 있는 노드를 취하여 중복된 value를 모두 제거한 새 노드를 output으로 표시합니다.
action (ReduceStrings) {
type (Constructor)
collect {
input (strings) {
type (String)
min (Optional)
max (Many)
}
}
output (String) {
evaluate {
$expr(dedupe(strings))
}
}
}