Solr7.4 Tagger Handler (NER,Named-Entity Recognition)
Solr 7.4.x version의 Tagger Handler를 이용한 NER(Named-Entity Recognition)
NER이란 자연어에서 뜻이 있는 단어를 뽑아내는 것이다. 챗봇처럼 자연어와 관련있는 기술에서 사용되는 기능인데, 예를 들어 "피자 주문할게요" 라는 질문이 있다. 이 문장에서 유추해 볼 수 있는 것은 "피자 주문" 이것을 더 보편화시켜 보면 "메뉴 주문"이라는 사용자질의 "의도"를 알 수 있다. 만약 "햄버거 주문할게요"라는 질의가 있으면 이 또한 "메뉴 주문"이라는 의도라는 것을 유추할 수 있다. 그럼 사용자가 어떠한 메뉴를 주문한다는 것은 알겠는데 그럼 그 메뉴가 무엇인가? 이러한 것이 챗봇에서는 NER이라는 기술로 추출해 낼 수 있는 단어라는 것이다. "피자 주문할게요"라는 질의의 의도는 "메뉴 주문" 개체명(Named-Entity)는 "피자"가 되는 것이다. 이렇게 의미있는 단어를 뽑아내는 것은 아주 중요한 챗봇의 기술이며 앞으로 더욱 발전해야할 기술이기도 하다. 이 NER 기술을 solr 7.4의 Tagger Handler를 이용하여 구현해 볼 것이다.
모든 구현은 Mac OS 환경에서 구현하였습니다.
우선 구현에 앞서 선행되어야 하는 것이, 바로 이전의 글인 Solr와 Zookeeper 연동입니다. 모든 환경은 solr cloud 환경에서 구현하였기에 중복되는 설명은 배제하였습니다.
$SOLR_HOME/server/solr 폴더 밑에 configset이 존재할 것입니다. 그 폴더를 보면 디폴트 환경설정 파일이 있는데, 그 안의 schema.xml과 solrconfig.xml 파일을 만질 것입니다. 이전에 따로 사용중이셨던 설정파일을 이용하셔도 무관합니다.
<schema.xml>
<field name="DOCID" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="NER_VALUE" type="text_general" indexed="true"/>
<field name="NER_KEY" type="string" indexed="true"/>
<field name="NER_TAG" type="tag" stored="false"/>
<copyField source="NER_VALUE" dest="NER_TAG"/>
<uniqueKey>DOCID</uniqueKey>
<fieldtype name="tag" class="solr.TextField" positionIncrementGap="100" postingsFormat="FST50"
omitTermFreqAndPositions="true" omitNorms="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.ConcatenateGraphFilterFactory" preservePositionIncrements="false"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldtype>
적당한 위치에 선언해줍니다. NER과 관련된 필드들과 필드 타입을 선언한 설정입니다.
<solrconfig.xml>
<requestHandler name="/tag" class="solr.TaggerRequestHandler">
<lst name="defaults">
<str name="field">NER_TAG</str>
</lst>
</requestHandler>
적당한 위치에 선언해줍니다. 개체명을 추출하기 위한 Tagger Handler를 등록하는 설정입니다.
만약 디폴트 설정파일을 이용하지 않고 새로 정의하셨다면 해당 설정 폴더를 SolrConifg/conf/ 밑으로 넣어줍니다.(SolrConfg는 맘대로정의 가능하지만 conf는 맞춰주셔야합니다.)
solr 디렉토리의 적당한 곳에 위치시켜줍니다. 그리고 난 후에 zookeeper에 upconfig를 합니다.(solr collection들이 사용할 설정파일을 zookeeper에 업로드하여 중앙에서 관리해줍니다.)
저는 앞으로 자주 사용할 가능성이 있다 판단이 되어서 쉘스크립트 실행파일을 만들어서 upconfig 했습니다.
<uploadSolrConfig.sh>
#!/bin/bash
# usage uploadSolrConfig.sh zipConfigPath configName zkServers
CONFIG_PATH=$1
CONFIG_NAME=$2
ZK_SERVERS=$3
# upload config info
$HOME/solr/bin/solr zk upconfig -n $CONFIG_NAME -d $CONFIG_PATH -z $ZK_SERVERS
echo $?
~$ ./uploadSolrConfig $SOLR_HOME/SolrConfig TaggerHandlerConf localhost:2181,localhost:2182,localhost:2183 으로 실행시켜줍니다.
이후 solr admin 페이지를 들어가서 cloud>file>confg에 생성한 이름으로 conf file이 생성되었는지 확인합니다. 그리고 Collection탭에 들어가서 생성한 conf file을 이용하여 컬렉션을 생성해줍니다.(collectionName = TaggerHandler)
<indexing file>
<add>
<doc>
<field name="DOCID">NER1</field>
<field name="NER_VALUE">햄버거</field>
<field name="NER_KEY">메뉴</field>
</doc>
<doc>
<field name="DOCID">NER2</field>
<field name="NER_VALUE">피자</field>
<field name="NER_KEY">메뉴</field>
</doc>
<doc>
<field name="DOCID">NER3</field>
<field name="NER_VALUE">치킨</field>
<field name="NER_KEY">메뉴</field>
</doc>
<doc>
<field name="DOCID">NER</field>
<field name="NER_VALUE">파스타</field>
<field name="NER_KEY">메뉴</field>
</doc>
</add>
그리고 색인할 파일을 만듭니다.
$SOLR_HOME/bin/post -c TaggerHandler $SOLR_HOME/menu.xml 로 색인해줍니다.
이제 모든 작업이 끝이 났고, 적당한 request를 보내서 결과를 확인하면 됩니다.
요청은 POST 방식이고, 요청헤더에 Content-Type text/plain 요청바디에 "햄버거, 피자,피자 주문할게요"라는 질의를 넣고 밑의 요청을 보내면 (url 테스트를 위하여 저는 간편한 postman이라는 툴을 사용하였습니다. curl을 사용해도 무관합니다.)
http://localhost:8983/solr/TaggerHandler/tag?overlaps=NO_SUB&tagsLimit=5000&fl=DOCID,NER_VALUE,NER_KEY&wt=json&intent=on
{
"responseHeader": {
"status": 0,
"QTime": 35
},
"tagsCount": 3,
"tags": [
[
"startOffset",
0,
"endOffset",
3,
"ids",
[
"NER1"
]
],
[
"startOffset",
5,
"endOffset",
7,
"ids",
[
"NER2"
]
],
[
"startOffset",
8,
"endOffset",
10,
"ids",
[
"NER2"
]
]
],
"response": {
"numFound": 2,
"start": 0,
"docs": [
{
"DOCID": "NER1",
"NER_VALUE": "햄버거",
"NER_KEY": "메뉴"
},
{
"DOCID": "NER2",
"NER_VALUE": "피자",
"NER_KEY": "메뉴"
}
]
}
}
=>이런 결과가 나옵니다!!!
출처: https://coding-start.tistory.com/57?category=757916 [코딩스타트]
'Elastic Stack > ElasticSearch' 카테고리의 다른 글
Elasticsearch - 4.한글 형태소분석기(Nori Analyzer) (0) | 2021.04.19 |
---|---|
Elasticsearch - 3.부가적인 검색 API (0) | 2021.04.19 |
Elasticsearch - 2.검색 API(Elasticsearch Query DSL) (0) | 2021.04.19 |
ELK - Filebeat 란? (실시간 로그 수집) (0) | 2021.04.19 |
Solr&Zookeeper(솔라&주키퍼) cloud 환경 구성 (0) | 2021.04.19 |
Elasticsearch 로컬(1개의 클러스터)에서 n개 이상 노드띄우기 (0) | 2021.04.19 |
엘라스틱서치(elasticsearch) 5.4 설치 (0) | 2021.03.24 |
Elasticsearch 정리 (0) | 2021.01.07 |