🙆

Azure OpenAIとLlamaIndexとGradioを用いたRAG型チャットの作成

2024/12/16に公開

概要

Azure OpenAIとLlamaIndexとGradioを用いたRAG型チャットの作成を試みたので、備忘録です。

Azure OpenAI

Azure OpenAIを作成します。

その後、「エンドポイント:エンドポイントを表示するには、ここをクリックします」をクリックして、エンドポイントとキーを控えておきます。

その後、Azure OpenAI Serviceに移動します。

「モデルカタログ」に移動して、「gpt-4o」と「text-embedding-3-small」をデプロイします。

結果、以下のように表示されます。

テキストのダウンロード

今回は、青空文庫で公開されている源氏物語を対象とします。

https://www.aozora.gr.jp/index_pages/person52.html

以下により、一括ダウンロードします。

import requests
from bs4 import BeautifulSoup
import os

url = "https://genji.dl.itc.u-tokyo.ac.jp/data/info.json"

response = requests.get(url).json()

selections = response["selections"]

for selection in selections:

    members = selection["members"]

    for member in members:

        aozora_urls = []

        for metadata in member["metadata"]:

            if metadata["label"] == "aozora":

                aozora_urls = metadata["value"].split(", ")

        for aozora_url in aozora_urls:

            filename = aozora_url.split("/")[-1].split(".")[0]

            opath = f"data/text/{filename}.txt"

            if os.path.exists(opath):
                continue
                # pass

            response = requests.get(aozora_url)

            response.encoding = response.apparent_encoding

            soup = BeautifulSoup(response.text, "html.parser")

            div = soup.find("div", class_="main_text")        

            txt = div.get_text().strip()

            os.makedirs(os.path.dirname(opath), exist_ok=True)

            with open(opath, "w") as f:
                f.write(txt)

Indexの作成

環境変数を用意します。

.env
AZURE_OPENAI_ENDPOINT=xxxx
AZURE_OPENAI_API_KEY=xxxx

そして、以下により、indexを作成します。

import os
from llama_index.llms.azure_openai import AzureOpenAI
from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
from llama_index.core import SimpleDirectoryReader, Settings, VectorStoreIndex

# 環境変数
api_key = os.getenv("AZURE_OPENAI_API_KEY")
api_version = "2024-05-01-preview"
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")

# LLM
llm = AzureOpenAI(
    model="gpt-4o",
    deployment_name="gpt-4o",
    api_key=api_key,
    azure_endpoint=azure_endpoint,
    api_version=api_version,
)

# Embedding
embed_model = AzureOpenAIEmbedding(
    model="text-embedding-3-small",
    deployment_name="text-embedding-3-small",
    api_key=api_key,
    azure_endpoint=azure_endpoint,
    api_version=api_version,
)

Settings.llm = llm
Settings.embed_model = embed_model

# Data Source -> Documents化を行うStep
documents = SimpleDirectoryReader(
    input_dir="./data/text"
).load_data()

# 保存
index = VectorStoreIndex.from_documents(documents)
index.storage_context.persist(persist_dir="./data/index")

Gradio

最後にGradioを用いたアプリを作成します。

import os
import gradio as gr
from llama_index.core import StorageContext, load_index_from_storage, Settings
from llama_index.llms.azure_openai import AzureOpenAI
from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding

api_key = os.getenv("AZURE_OPENAI_API_KEY")
api_version = "2024-05-01-preview"
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")

llm = AzureOpenAI(
    model="gpt-4o",
    deployment_name="gpt-4o",
    api_key=api_key,
    azure_endpoint=azure_endpoint,
    api_version=api_version,
)

# You need to deploy your own embedding model as well as your own chat completion model
embed_model = AzureOpenAIEmbedding(
    model="text-embedding-3-small",
    deployment_name="text-embedding-3-small",
    api_key=api_key,
    azure_endpoint=azure_endpoint,
    api_version=api_version,
)

Settings.llm = llm
Settings.embed_model = embed_model

# rebuild storage context
storage_context = StorageContext.from_defaults(persist_dir="./data/index")

# load index
index = load_index_from_storage(storage_context)

query_engine = index.as_query_engine(similarity_top_k=10)

# Function to handle chat messages with history
def echo(message, history):
    print("History:", history)
    context = "\n".join([f"User: {user_msg}\nBot: {bot_msg}" for user_msg, bot_msg in history])
    full_context = f"{context}\nUser: {message}"
    response = query_engine.query(full_context).response
    history.append((message, response))
    return response # history

demo = gr.ChatInterface(
    fn=echo, 
    examples=[
        "光源氏はどのような人物ですか?",
        "夕顔はどのような人物ですか?"
    ], 
    title="Llama Index Chatbot",
)
demo.launch()

以下のように、チャットボットを作成できました。

まとめ

間違った理解をしている点があるかもしれませんが、参考になりましたら幸いです。

Discussion