その他

【ゴミ分別AI】ゴミ出しLMを作ってみた! その2

その他
この記事は約5分で読めます。

はじめに

みなさん、こんにちは。もう5月も終わりですね・・・。4月からあっという間の2ヶ月が終わろうとしています。

前回はローカルLLMを使って、ゴミ出しの情報を答えるゴミ出LMを製作してみました。まだご覧になられてない方がいらっしゃいましたら、ぜひご覧ください!

今回は、これに応用編ということで、OPENAI_API_KEYを使って、より性能の高いゴミ出しLMへ進化させていきいたいと思います!

ちょっと寄り道。RAGについて。

前回、用語の整理としてLMやLLMなどについて語りました。今回も少し用語を紹介です。

今作っているシステムは、RAG(Retrieval Augmented Generation)といい、検索拡張生成というシステムになります。
普段使用しているLLM(chatGPTなどのツール)に、新しい知識を与えて常に最新の回答や、正確な回答ができるようにしておく技術になります。

さらに詳しく知りたい人は、以下の記事を参考にしてみてください!

RAG とは何ですか? - 検索拡張生成 AI の説明 - AWS
検索拡張生成 (RAG) とは何か、企業が RAG AI を使用する方法と理由、および RAG を AWS で使用する方法。

作ってみる

前回との変更点

それでは早速作っていくのですが、前回と何が違うのかだけ、先に紹介しておきます。

今回大きく変わってくるのは、LLMのモデルEmbedding生成の部分です。
前回作ったゴミ出しLMは、LLMのモデルOllamaEmbedding生成Sentence-transformersというのを使ってきました。今回は、この二つの役割を、OPENAI_API_KEYを使うことで、OpenAIのGPTやopenai.Embedding.createでこなすことができます。

ただ、前回の記事でも書いたように、これらには課金が発生するので、注意が必要です!

プログラムをつくる

今回は、札幌市の情報でゴミ出しLMを作っていきます。
全体的なプログラムの処理は、webページのテキスト抽出をしてから、テキストをチャンク分割します。その分割したテキストを、EmbeddingとFAISSで保存し、質問に対して回答を生成するというものです。

# ① Webページのテキスト抽出
def scrape_text(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")
    return soup.get_text()

# ② テキストをチャンク分割
def chunk_text(text, chunk_size=500, chunk_overlap=50):
    splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
    return splitter.split_text(text)

# ③ EmbeddingとFAISSで保存
def create_vector_store(chunks):
    embeddings = OpenAIEmbeddings()
    return FAISS.from_texts(chunks, embeddings)

# ④ 質問を処理して回答を生成
def ask_question(vectorstore, query):
    retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
    qa = RetrievalQA.from_chain_type(
        llm=ChatOpenAI(temperature=0, model="gpt-4"),
        chain_type="stuff",
        retriever=retriever
    )
    return qa.run(query)

しかし、壁・・・。

しかし、このプログラムでいざ質問をしようとすると、なぜかうまく回答をしてくれません。質問に対して、答えるために情報が少ないと言ってきたり、誤った情報を提供してきたりします。これはなぜでしょうか・・・?

情報が取得できず回答できない例
誤った回答をする例

調べ進めてみると、どうやらwebから情報を抽出するときに、正しく情報が抽出できていないことがわかりました。それは、抽出した情報が文字化けや、HTMLの構造が複雑で正しく情報を抽出できていないことが原因でした。

また、最近弊社に導入されたAIエージェントのDevinにも、原因究明を手伝ってもらいました。すると、スクレイピング機能の問題点や、RAGパイプラインの最適化不足などを提案してくれました。また、その問題点について修正もしてくれました。天才!
(今後、Devinに関する記事も増やしていきますので、ぜひご覧ください!!)

再度実行してみる

修正してくれたコードを実行してみると、今度は問題なく回答をしてくれました!
また、ただゴミの名前だけでなく、備考欄の項目についても回答することができています。素晴らしいですね!

まとめ

さて、今回はゴミ出しLMの第二弾ということで、OPENAI_API_KEYを使用してLLMのモデルEmbedding生成の部分をそれぞれ代用させてみました。こうすることで、オンラインでも操作することができるようになり、ますます実用性が増したと思います。

今回作ったコードも、GitHubに共有していますので、ぜひご覧ください。

GitHub - iwasakiterukazuimpl/gomi-llm2
Contribute to iwasakiterukazuimpl/gomi-llm2 development by creating an account on GitHub.

今回もご覧いただき、ありがとうございました!