30
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ChatGPT初心者でもわかる 「Chain of Thought をPythonで100行で実装してみた」

Last updated at Posted at 2023-03-05

最近、どっぷりLLMにハマっているsonesuke( https://twitter.com/sonesuke )です。

前回はChain of Thoughtの基本的な考え方を紹介しました。全体像を知りたい方は、ぜひ前回の記事も参照してください。

今回は、OpenAIのAPIを使って実装していきます。

TL;DR

  1. Chain of ThoughtのPython実装です
  2. 成果物はこちら

前提条件

  • openai==0.27.0
  • google-api-python-client==2.80.0
  • requests==2.28.2
  • beautifulsoup4==4.11.2

OpenAIのAPI キー

親切な人が、APIキーの取得までの手順を書いてくださっているので、それを参考に取得します。

終わったら、OpenAIのpipモジュールを取得しましょう。

pip install openai==0.27.0

今回使用する、gpt-3.5-turbo (ChatGPTのエンジン)は、0.27.0以上でないと使えないので0.27.0以上を取得しましょう。

OpenAIのAPIキーを取得する際にクレジットカードが必要になります。使いすぎると、そこそこお高いので、注意して使いましょう。

Google Custom Search API キー

こちらも、親切な人がAPIキーと、Custom Search Engine IDの取得方法を書いてくださっているので参考にさせていただきましょう。

終わったら、Google APIのPython クライアントのpipモジュールを取得しましょう。

pip install google-api-python-client==2.80.0

ちなみに、Google Custom Search APIを使わずに、Googleをスクレイピングすると、利用規約違反になるらしいです。怖かったので素直に従っておきました。

その他のモジュール

他のスクレイピングに使用するモジュールもインストールしてしまいます。

pip install requests beautifulsoup4

requestsはPythonでHTTP通信するためのモジュール、beautifulsoup4は、HTMLのパースに使用します。

コーディング

まずは初期化とAPIキーのセットです。

OPEN_AI_KEY = "ここにOpenAIのAPIキーをいれます"
GOOGLE_API_KEY = "ここにGoogle Custom SearchのAPIキーをいれます"
CUSTOM_SEARCH_ENGINE_ID = "ここにGoogle Custom Search EngineのIDをいれます"

openai.api_key = OPEN_AI_KEY

上のコードのキーの部分は、前提条件で取得した各種キーを入れましょう。

ユーザーからの問いは、前回記事と同様のチェンソーマンにします。

query = "チェンソーマンのアニメ化はいつされた?"

最初の問い (Prompt)

では、早速、最初の問いをコーディングしていきます。

template = """
次の入力文から検索すべきキーワードを3つ出し出力文に従って出力しなさい。

# 出力文
[キーワード], [キーワード], [キーワード]

# 入力文
{query}
"""
prompt = template.format(query=query)

# 検索キーワードをどうしたらよいかChatGPTに聞く
completion = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
    {"role": "user", "content": prompt}])
answer = completion.choices[0].message.content
print("1つめの問いに対する答え:\n" + answer)

ひな形(template)に質問(query)を流し込み、質問(prompt)を完成させ、openaiのAPIに、その質問を入れて、問い合わせをします。結果は、completionの中に返ってきます。

これが、1つめの問いに対する答え

1つめの問いに対する答え:
チェンソーマン, アニメ化, いつ

ちゃんとカンマ区切りで答えてくれました。いい感じです。

2つめの問い(Prompt)

2つめの問いに行く前に、調べるべきWebページを検索して見つけましょう。

# ググる
keywords = answer.split(",")
service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY)
result = service.cse().list(
     q= " ".join(keywords),
     cx=CUSTOM_SEARCH_ENGINE_ID,
     lr='lang_ja', # 日本語で
     num=3, # とりあえず 3 ウェブサイト
     start=1 # 検索結果1ページ目
     ).execute()

1つめの結果からキーワードを抽出し、Google Custom Search APIを使用して、Google検索を行います。とりあえず、3ページぐらい取得してみました。

その後、各ページごとにスクレイピングして、bodyタグ内の文字列を集めます。

for item in result["items"]:
    url = item["link"]

    # ヒットしたURLをスクレイピングします
    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")
    body = soup.body # body要素の取得
    text = body.get_text() # body要素内のテキストを抜き出す

取れた文字列をコンテキストとして渡して、ChatGPTに問い合わせます。

    template = """
    次のコンテキストを読み取って、入力文に関する情報を箇条書きで3つ書いてください。

    # 入力文
    {query}

    # 出力文
    - [情報]
    - [情報]
    - [情報]

    # コンテキスト
    {context}
    """
    prompt = template.format(context=text[:2000], query=query)

    # スクレイピングした情報を与えて関係ある情報を集める
    completion = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
        {"role": "user", "content": prompt}])
    answer = completion.choices[0].message.content
    print("2つめの問いに対する答え:\n" + answer)
    answers.append(answer)

こんな感じの答えが返ってきました。

2つめの問いに対する答え:
- アニメ化された
- 放送開始時期は2022年10月11日
- 最速配信はPrime Videoにて25:00より実施

2つめの問いに対する答え:
- 入力文はチェンソーマンのアニメ化はいつされた?」である
- アニメチェンソーマン1期は2022年10月12月に放送されたことがわかる
- 現時点でアニメチェンソーマン2期の制作は未定だが原作コミックのストーリーが残っていることから2期が制作される可能性は高いとされている

2つめの問いに対する答え:
- 入力文はチェンソーマンに関する情報を問い合わせている
- 入力文の内容はアニメ化に関する情報を求めている
- 入力文に詳しい回答が得られなかった可能性がある

質問文に対する答えが入っていますね。

3つ目の問い(Prompt)

最後にこれまでの調査結果を使って、質問の答えを完成させます。

template = """
入力文にたいし、コンテキストから推測される回答を答えなさい。

# コンテキスト
{context}

# 入力文
{query}
"""
prompt = template.format(context="\n".join(answers), query=query)

# 集めた情報をコンテキストとして渡して最終の答えを出させる。
completion = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
    {"role": "user", "content": prompt}])
answer = completion.choices[0].message.content
print("最終の答え:\n" + answer)

2つめの問いで取得したanswersを連結してコンテキストとして、promptに埋め込みます。
返ってきた答えがこちら。

最終の答え:
2. アニメチェンソーマンの放送開始時期は2022年10月11日である
また最速配信はPrime Videoにて25:00より実施される

いいですね。

想定されていた答えが出ました。一部、「2.」とかよくわからないものがついていたりしますが、丁寧にやれば除去できるでしょう。今回は複雑になってしまうのでこの辺にしておきます。

まとめ

いかがだったでしょうか?
プログラム的に質問を連鎖させることでChain of Thought感が出てきましたね。

今回は、前回紹介したChain of Thoughtを、OpenAIのAPIを使ってChatGPTを使用し、Google Custom Search APIを使用し最新情報をChatGPTに教えながら、正しい回答を出すことができました。

とはいえ・・・・・プログラム書くのめんどくさくね?って思ったあなた。いい勘しています。
次回は、これらをフレームワークしてきたライブラリをご紹介します。

30
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?