※llama-indexのバージョンが上がり、この記事の内容はそのままでは動かなくなっております。
    !pip install llama-index
            ↓
    !pip install llama-index==0.6.0
に読み替えていただければと思います。


5/12に開催されましたCDLE DAY in AI EXPO 2023春の「生成AIセッション」の資料を共有いたします。なお、AIベンダーについての話につきましては、実際に現地で話をした内容に書き換えております。

補足をしておきますと、私の後に生成AIセッションで発表された遠藤太一郎さんのように、しっかりとした考えを持ってサービスを行っているAIベンダーも沢山存在します。
しかし、「ChatGPTが人気だし、安易に作ってサービスとして売ろう」という会社もあるような気がします。

その見極めを行い、何をどのように実現したいかをしっかり考えるには「手を動かして実装してみる」という事は非常に重要かと思います。

おまけとして、当日のスライドになかったGoogle Colabで動かすことが出来る、Flaskの実装部分を含めたプログラムを下記に記述いたします。

インデックスの作成

# パッケージのインストール
!pip install llama-index


import os
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader

# APIキー
os.environ["OPENAI_API_KEY"] = "......."

# インデックスの作成
documents = SimpleDirectoryReader("data").load_data()
index = GPTVectorStoreIndex.from_documents(documents)

# インデックスの保存
index.storage_context.persist()


チャットボットの実装

project_name = "名古屋チャットボット"
port = "8000" 
host = True 
from google.colab.output import eval_js
host = eval_js(f"google.colab.kernel.proxyPort({str(port)})")


#@title chat.py
chat_py_string = '''

from flask import Flask, redirect ,request,render_template,jsonify
from llama_index import StorageContext, load_index_from_storage

import json
import requests

app = Flask(__name__)

@app.route("/")
def check():
    return render_template("chat.html")

@app.route("/output", methods=["POST"])
def output():
    try:
        q_text = request.json["_A"]
        print(q_text)

        # インデックスの読込
        # rebuild storage context
        storage_context = StorageContext.from_defaults(persist_dir="./storage")
        # load index
        index = load_index_from_storage(storage_context)

        # 質問応答
        query_engine = index.as_query_engine()
        res=str(query_engine.query(q_text + "、日本語で答えてください。"))
        print("【質疑応答結果】")
        print(res)

        data = {"result":res, "msg":res}
        return jsonify(ResultSet=json.dumps(data)), 200
    except Exception as err:
        print(err)
        data = {"error":"err"}
        return jsonify(ResultSet=json.dumps(data)), 500

if __name__ == "__main__":
    import sys
    args = sys.argv
    app.run(debug=True, port=args[1])

'''.strip()


#@title chat.html
chat_html_string = '''

<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>名古屋について何でも聞いてください</title>
</head>
<body>
    <input type="text" size="60" value="名古屋" name="_A" /> <button id="run">送信</button><br/>
    <h2>結果</h2>
    <script src="static/post.js"></script>
</body>
</html>

'''.strip()


#@title post.js
post_js_string='''

fetch("https://code.jquery.com/jquery-3.4.1.min.js").then(r=>{return r.text()}).then(t=>eval(t)).then(()=>{
 $=jQuery;
    document.getElementById("run").addEventListener("click",
        function(){
            values=[...document.querySelectorAll("input")].map(_=>_.value);
            document.getElementById("run").setAttribute("disabled", true);
            $.ajax({
                url:"/output",
                type:"POST",
                data:JSON.stringify({"_A":values[0]}),
                contentType:"application/json"
            }).done(data=>{
                document.getElementById("run").removeAttribute("disabled");
                $(document.body).append(JSON.parse(data.ResultSet).msg,"<br/>");
            }).fail(data=>{
                document.getElementById("run").removeAttribute("disabled");
                $(document.body).append("error","<br/>")
            });
        },false);
});

'''.strip()


!rm -rf $project_name
!mkdir $project_name && mkdir $project_name/templates && mkdir $project_name/static
!echo -e '{chat_py_string}' >> $project_name/chat.py
!echo -e '{chat_html_string}' >> $project_name/templates/chat.html
!echo -e '{post_js_string}' >> $project_name/static/post.js


print('↓のurlにアクセスする')
print(host)

!python $project_name/chat.py $port


CDLEメンバーではない方はこちらの資料をご確認ください。