チャット UI を簡単に作れる「Chainlit」の紹介 ~ LangChain との統合 ~

# Chainlit とは?
https://github.com/Chainlit/chainlit

**Chainlit** は Python で ChatGPT のような UI を作れるライブラリです.
[LangChain](https://github.com/langchain-ai/langchain) と統合されているため, 簡単に UI を作れます.

今回は例として, 入力された文章を関西弁に変換するチェーンをあらかじめ用意しておきます.

```console
$ pip install langchain langchain_openai
```

```python:my_chain.py
from langchain.chains import LLMChain
from langchain.chains.base import Chain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

template = """関西弁に変換してください.
- 変換前: {input}
- 変換後: """


def create_chain() -> Chain:
    llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo", streaming=True)
    prompt = PromptTemplate(template=template, input_variables=["input"])
    return LLMChain(prompt=prompt, llm=llm, verbose=True)
```


# Chainlit で UI を作る

まず chainlit を install します.

```console
$ pip install chainlit
```

[公式ドキュメント](https://docs.chainlit.io/integrations/langchain) を参考に, 以下のようなコードを書きます.

```python:my_chat.py
import my_chain
import chainlit as cl
from langchain.chains.base import Chain
from typing import cast


@cl.on_chat_start
def on_chat_start():
    # チェーンをインスタンス化
    chain = my_chain.create_chain()

    # チェーンをセッションに保存
    cl.user_session.set("chain", chain)


@cl.on_message
async def on_message(query: cl.Message):
    # チェーンをセッションから取得
    chain = cast(Chain, cl.user_session.get("chain"))

    # チェーンを呼び出し
    res = await chain.acall(query.content, callbacks=[cl.AsyncLangchainCallbackHandler()])

    # チェーンの応答を送信
    await cl.Message(content=res["text"]).send()
```

Chainlit は [`.env` ファイルを自動で読み込む](https://docs.chainlit.io/backend/env-variables)ため, `OPENAI_API_KEY` を書いておきます.

```.env
OPENAI_API_KEY=*****
```

これでもうチャット UI が完成しました. `chainlit run` で起動します.

```console
$ chainlit run my_chat.py
2025-04-29 13:01:20 - Created default config file at /Users/skkzsh/path/to/.chainlit/config.toml
2025-04-29 13:01:20 - Created default translation directory at /Users/skkzsh/path/to/.chainlit/translations
2025-04-29 13:01:20 - Created default translation file at /Users/skkzsh/path/to/.chainlit/translations/en-US.json
2025-04-29 13:01:20 - Loaded .env file
2025-04-29 13:01:20 - Created default chainlit markdown file at /Users/skkzsh/path/to/chainlit.md
2025-04-29 13:01:20 - Your app is available at http://localhost:8000
```

http://localhost:8000 でチャット UI にアクセスできます. [^1]

[^1]: `--port` オプションでポートをデフォルトの8000番から変えられます

<!-- ![welcome_to_chainlit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/77561082-e0c5-6702-c138-7e69d7b4a6c2.png) -->

![welcome_to_chainlit_1.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/5033ddce-29bb-4795-8395-dbc732b18240.png)

チャットしてみると以下のような感じです.

<!-- ![chat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/9c4343eb-0047-fc62-3170-4e5a11eb7d43.png) -->

![chat_1.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/00fe3b2c-261c-4459-abcc-7e1a50ced959.png)


# 推論プロセスの視覚化 (と中間ステップのデバッグ)

「You」と「Chatbot」の間にある「**Took ◯ steps**」を展開すると, 推論プロセスも UI から確認することができます.
これにより, 推論がどのように進行し, 各ステップがどのように機能しているかを視覚的に追跡することができます.

<!-- <img width="400" alt="CoT" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/e3ff0e74-9579-ede3-3f31-4be56afc8542.png"> -->

<img width="450" alt="CoT_1.0" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/a04eba59-bac4-4dda-80b6-754988f8b7dc.png">

この例では単純なチェーンですが, より複雑なチェーンを作ると, 「[思考の連鎖](https://docs.chainlit.io/concepts/chain-of-thought)」の過程をより視覚的に把握することができます.

さらに「Inspect in prompt playground」(最下のターミナルのようなアイコン) を押下すると, [**Prompt playground**](https://docs.chainlit.io/concepts/prompt-playground) 画面が開きます.

<!-- <img width="500" alt="playground" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/dcb46ecf-4f9a-7437-15ef-d466a9b61234.png"> -->

![playground_1.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6361/8ec421f8-5bb7-438f-90ae-971b64c60a5d.png)


これにより, 中間ステップのプロンプトでデバッグしたり,
model や temperature などのパラメータを変更したりすることが可能です.

# バージョン情報
- Chainlit 1.0.506
- LangChain 0.3.24
- Python 3.13.3