1. ninomiyt

    No comment

    ninomiyt
Changes in body
Source | HTML | Preview
@@ -1,136 +1,161 @@
Microsoft Azureの自然言語処理サービスの[LUIS(Language Understanding Intelligent Service)](https://azure.microsoft.com/ja-jp/services/cognitive-services/language-understanding-intelligent-service/)は非常に便利です。
-文脈(Intents)(Entities)
+会話の**意図(Intents)**と**エンティティ(Entities)**を同時に抽出することができ、簡単な会話応答プログラムやチャットボットであれば簡単に作ることができます。(エンティティとは抽出したい単語のことです)
https://www.luis.ai/
+ところが、エンティティを入力していくのは割と骨が折れる作業です。
+
+![image.png](https://qiita-image-store.s3.amazonaws.com/0/127762/89383d10-9f4a-9b6d-0c47-d59e2aa1a43e.png)
+
+ブラウザ画面を使うと、上の画像のように、例文と「ここからここまでが抽出したいエンティティ」というのをひとつひとつ入力していく必要があり、なかなか根気のいる作業でした。
+
+# 作戦
+
+LUISには、JSONのエクスポートとインポート機能が備わっています。
+
+![image.png](https://qiita-image-store.s3.amazonaws.com/0/127762/659a52ef-e26f-6bb0-4f62-aab68e6f2530.png)
+
+上記画面の[アプリケーションのトップページ](https://www.luis.ai/applications)のそれぞれのアプリケーションの```{}```でエクスポートできますし、```Import App```でアップロードしなおすことができます。
+
+そのため、
+
+* 以下のようなExcel上で情報を入力する
+* csvに書き出す
+* PythonのスクリプトでJSONに変換する
+
+![image.png](https://qiita-image-store.s3.amazonaws.com/0/127762/96006801-eae4-59de-dbf2-26be7c1f3464.png)
+
+
# Pythonスクリプト
JSONファイルを生成するために、次のようなスクリプトを用意します。
+細かい設定やファイル名は固定値で入れていますが、今回は書き捨てのコードだし、追加するにしても多少のコード変更で済むと思うので許してください。
+
```python3
#!/usr/bin/env python3
import json
import csv
from collections import defaultdict, OrderedDict
def main():
df = _read_csv('./input.csv')
output = _create_output(df)
print(json.dumps(output))
class DataFrame(list):
def __getitem__(self, key: str) -> list:
return [x[key] for x in self]
def keys(self) -> set:
res = set()
for x in self:
for y in x.keys():
res.add(y)
return res
def _create_output(df: DataFrame) -> OrderedDict:
entity_keys = df.keys() - {'text', 'Entities', 'intent'}
entities = _create_entities(entity_keys)
intents = _create_intents(df['intent'])
utterrances = _create_utterances(df, entity_keys)
return _create_luis_schema(intents, entities, utterrances)
def _read_csv(path: str) -> DataFrame:
with open(path, 'r', encoding='utf8') as f:
df = DataFrame(l for l in csv.DictReader(f) if l)
return df
def _create_entities(entities: list) -> list:
res = []
for name, children in _parse_entities(entities).items():
cs = [c for c in children if c is not None]
res.append(_create_entity(name, cs))
return res
def _create_intents(intents: list) -> list:
res = set(intents)
res.add('None')
return [{'name': n} for n in res]
def _parse_entities(entities: list) -> defaultdict(set):
res = defaultdict(set)
for entity in entities:
name, child = _parse_entity(entity)
res[name].add(child)
return res
def _parse_entity(entity: str) -> tuple:
if '::' not in entity:
return (entity, None)
return tuple(entity.split('::'))
def _create_entity(name: str, children: set) -> OrderedDict:
res = OrderedDict([('name', name)])
if len(children) >= 1:
res['children'] = list(children)
return res
def _create_utterances(rows: DataFrame, entity_keys) -> list:
return [_create_utterrance(x, entity_keys) for x in rows]
def _create_utterrance(row: dict, entity_keys: set) -> OrderedDict:
return OrderedDict([
('text', row['text']),
('intent', row['intent']),
('entities', _create_utterrance_entities(
row['text'], [(k, row[k]) for k in entity_keys]))
])
def _create_utterrance_entities(text: str, entitity_items: list) -> list:
return [_create_utterrance_entity(text, k, v)
for k, v in entitity_items if v] # not ''
def _create_utterrance_entity(
text: str, entity_key: str, entity_value: str) -> OrderedDict:
start_pos = text.find(entity_value)
return OrderedDict([
('entity', entity_key),
('startPos', start_pos),
('endPos', start_pos + len(entity_value) - 1)
])
def _create_luis_schema(
intents: list, entities: list, utterrances: list) -> OrderedDict:
return OrderedDict([
('luis_schema_version', '2.1.0'),
('versionId', '0.1'),
('name', 'TestOperator'),
('desc', 'forTestOperator'),
('culture', 'ja-jp'),
('intents', intents),
('entities', entities),
('composites', []),
('closedLists', []),
('bing_entities', []),
('actions', []),
('model_features', []),
('regex_features', []),
('utterances', utterrances)
])
if __name__ == '__main__':
main()
```