Metadata-Version: 2.1
Name: dialog-reflection
Version: 0.1.2
Summary: A library for dialog systems that attempt to respond to messages as Reflective Listening.
License: GNU General Public License v3.0
Author: Sadahiro YOSHIKAWA
Requires-Python: >=3.10,<4.0
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Requires-Dist: katsuyo-text (==0.1.2)
Requires-Dist: spacy (>=3.4.1,<4.0.0)
Description-Content-Type: text/markdown

# Dialog Reflection

A library for dialog systems that attempt to respond to messages as Reflective Listening.

## Demo

Need `git` and `poetry` to run this demo.

```console
$ git clone git@github.com:sadahry/dialog-reflection.git
$ cd dialog-reflection
$ poetry install
$ poetry run python examples/interactive_ja.py
```

## Install

Need `python` >= `3.10`

```console
$ pip install dialog-reflection
```

## How to Use (Japanese)

SpaCyの日本語モデルのインストールが必要  
* `ja_ginza==5.1.2` でテスト済
* 他モデルの利用は可能だが推奨しない
  * 係り受けや形態素解析によって不整合があるため利用前にテストを推奨

```console
$ pip install ja_ginza==5.1.2
```

実行例

```python
from dialog_reflection.lang.ja.reflector import JaSpacyReflector


refactor = JaSpacyReflector(model="ja_ginza")

message = "今日は旅行へ行った"
reflection_text = refactor.reflect(message)

print(reflection_text)
# => 旅行へ行ったんですね。
```

Builderを使う例

```python
from dialog_reflection.lang.ja.reflection_text_builder import (
    JaSpacyPlainReflectionTextBuilder,
)
import spacy


nlp = spacy.load("ja_ginza")
builder = JaSpacyPlainReflectionTextBuilder()

message = "今日は旅行へ行った"
doc = nlp(message)
# some code...
reflection_text = builder.build(doc)

print(reflection_text)
# => 旅行へ行ったんですね。
```

### 語尾の調整

`op` を変更することで語尾を調整可能

```python
from dialog_reflection.lang.ja.reflector import JaSpacyReflector
from dialog_reflection.lang.ja.reflection_text_builder import (
    JaSpacyPlainReflectionTextBuilder,
)
from dialog_reflection.lang.ja.reflection_text_builder_option import (
    JaSpacyPlainReflectionTextBuilderOption,
)


refactor = JaSpacyReflector(
    model="ja_ginza",
    builder=JaSpacyPlainReflectionTextBuilder(
        op=JaSpacyPlainRelflectionTextBuilderOption(
            fn_last_token_taigen=lambda token: token.text + "なんだね。",
            fn_last_token_yougen=lambda token: token.lemma_ + "んだね。",
        )
    ),
)

message = "今日は旅行へ行った"
reflection_text = refactor.reflect(message)

print(reflection_text)
# => 旅行へ行ったんだね。
```

その他設定項目は [reflection_text_builder_option.py](https://github.com/sadahry/dialog-reflection/blob/main/dialog_reflection/lang/ja/reflection_text_builder_option.py#L24) を確認してください

### ロジックのカスタマイズ

`JaSpacyPlainReflectionTextBuilder` を override することでロジックをカスタマイズ可能

```python
from dialog_reflection.reflection_cancelled import (
    ReflectionCancelled,
)
from dialog_reflection.cancelled_reason import (
    NoValidSentence,
)
from dialog_reflection.lang.ja.reflector import JaSpacyReflector
from dialog_reflection.lang.ja.reflection_text_builder import (
    JaSpacyPlainReflectionTextBuilder,
)
import spacy


class CustomReflectionTextBuilder(JaSpacyPlainReflectionTextBuilder):
    def extract_tokens(self, doc: spacy.tokens.Doc) -> spacy.tokens.Span:
        propn_token = next(filter(lambda token: token.pos_ == "PROPN", doc), None)
        if propn_token is None:
            raise ReflectionCancelled(reason=NoValidSentence(doc=doc))
        if propn_token.dep_ in ["compound", "numpound"]:
            return doc[propn_token.i : propn_token.head.i + 1]
        return doc[propn_token.i : propn_token.i + 1]


refactor = JaSpacyReflector(
    model="ja_ginza",
    builder=CustomReflectionTextBuilder(),
)


message = "今日は田中さんと旅行へ行った"
reflection_text = refactor.reflect(message)

print(reflection_text)
# => 田中さんなんですね。
```

