見出し画像

ChatGPT-like ChatBot with Chainlit🤖

はじめに

私は、現在フリーランスのエンジニアで生成AI導入支援のプロジェクトに携わっています。

特に最近は、社内に蓄積された経理関連のドキュメントや議事録をもとに、LLM(Large Language Models)ベースでFAQ ChatBotなどを構築する受託案件がとても増えてきました。
ただ、いきなりエンジニアをアサインしてシステム開発するというよりは、前段としてまず、顧客からサンプルデータをもらい、どれくらいの精度で回答生成できるかを検証したり、イメージを掴んでもらうための簡易デモをサクッと作って先方とコミュニケーション取ることが多いです。

これまではよくStreamlitを使ってたのですが、色々調べていた中で、Streamlitよりも少ないコード量でリッチなUIを簡単に構築できるChainlitを見つけました。これなら顧客への提案からデモの展開までがよりスムーズに行える可能性がありそうだなと考えてます。

Chat画面

トークン単位で出力されている様子をお見せしたかったのですが、GIFだと中々アップロードできなかったので、とりあえずスクショのみで。

実際のコード

このコード量で、ストリーミング処理を含むChat画面が作れました。
今回はオープンソースのLLMを用いていますが、実際の現場ではGPT-4やClaude-3も使って社内メンバーへ共有し、結構良い反応をもらえてます。

もちろんPDFなどをアップロードしてRAGすることもできるので、今後も公式ドキュメントを参照しながら、いろんな機能を使い倒していきたいなと思ってます。

# app.py

import chainlit as cl
import ollama


@cl.set_chat_profiles
async def chat_profile():
    return [
        cl.ChatProfile(
            name="Mistral",
            markdown_description="The underlying LLM model is **Mistral**.",
            icon="https://picsum.photos/200",
        ),
        cl.ChatProfile(
            name="Llama 2",
            markdown_description="The underlying LLM model is **Llama 2**.",
            icon="https://picsum.photos/250",
        ),
    ]


@cl.on_chat_start
async def start_chat():
    await cl.Avatar(
        name="Chatbot", url="https://cdn-icons-png.flaticon.com/512/8649/8649595.png"
    ).send()
    await cl.Avatar(
        name="Error", url="https://cdn-icons-png.flaticon.com/512/8649/8649595.png"
    ).send()
    await cl.Avatar(
        name="You",
        url="https://media.architecturaldigest.com/photos/5f241de2c850b2a36b415024/master/w_1600%2Cc_limit/Luke-logo.png",
    ).send()
    chat_profile = cl.user_session.get("chat_profile")
    await cl.Message(
        content=f"A new chat session has started powered by {chat_profile}"
    ).send()

    system_content = "You are a helpful assistant."

    cl.user_session.set(
        "message_history",
        [{"role": "assistant", "content": system_content}],
    )


@cl.on_message
async def on_message(message: cl.Message):
    message_history = cl.user_session.get("message_history")
    message_history.append({"role": "user", "content": message.content})

    # Create the Chainlit response message
    msg = cl.Message(content="")

    chat_profile = cl.user_session.get("chat_profile")
    if chat_profile == "Mistral":
        deploymentId = "mistral"
    else:
        deploymentId = "llama2"

    stream = ollama.chat(
        model=deploymentId,
        messages=message_history,
        stream=True,
        options={"temperature": 0},
    )

    for chunk in stream:
        token = chunk["message"]["content"]
        await msg.stream_token(token)

    message_history.append({"role": "assistant", "content": msg.content})


この記事が気に入ったらサポートをしてみませんか?