generate_text で外部ツールを使用する

ai.google.dev で表示 Google Colab で実行 GitHub でソースを表示

ユースケースによっては、モデルからの生成を停止して、特定の結果を挿入したいことがあります。たとえば、言語モデルでは、文章問題などの複雑な算術問題で問題が発生することがあります。このチュートリアルでは、外部ツールで genai.generate_text メソッドを使用し、文章問題の正解を出力する例を示します。

この例では、numexpr ツールを使用して算術を実行しますが、同じ手順を使用して、ユースケースに固有の他のツールを統合することもできます。手順の概要は次のとおりです。

  1. ツールに送信するテキストを区切る start タグと end タグを決定します。
  2. 結果でのタグの使用方法をモデルに指示するプロンプトを作成します。
  3. generate_text に渡される stop_sequencesend タグを含めます。
  4. モデルの結果から、start タグと end タグの間のテキストをツールへの入力として受け取ります。
  5. ツールを実行し、出力をプロンプトに追加します。
  6. もう一度 generate_text を呼び出して、モデルでツールの出力を続行します。

設定

pip install -q google.generativeai
import google.generativeai as genai
genai.configure(api_key='YOUR API KEY')

from google.api_core import retry

@retry.Retry()
def generate_text(*args, **kwargs):
  return genai.generate_text(*args, **kwargs)
models = [m for m in genai.list_models() if 'generateText' in m.supported_generation_methods]
model = models[0].name
print(model)
models/text-bison-001

問題を直接解決する

解く問題は次のとおりです。

question = """
I have 77 houses, each with 31 cats.
Each cat owns 14 mittens, and 6 hats.
Each mitten was knit from 141m of yarn, each hat from 55m.
How much yarn was needed to make all the items?
"""
prompt_template = """
You are an expert at solving word problems. Here's one:

{question}

Work through it step by step, and show your work.
One step per line.

Your solution:
"""

次のように試してみましょう。

completion = generate_text(
    model=model,
    prompt=prompt_template.format(question=question),
    # The maximum length of the response
    max_output_tokens=800,
)

print(completion.result)
In the houses there are 77 * 31 = 2387 cats.
So they need 2387 * 14 = 33418 mittens.
And they need 2387 * 6 = 14322 hats.
In total they need 33418 * 141 + 14322 * 55 = 5554525m of yarn.
The answer: 5554525.

通常、このプロンプトはそのままで間違った結果を返します。一般的に、ステップは正しく認識されますが、算術は正しくありません。

答えは次のとおりです。

answer = 77*31*14*141 + 77*31*6*55
answer
5499648

電卓を使用するようにモデルに指示する

次回は、計算ツールへのアクセス方法をモデルに伝えます。そのためには、計算が必要な場所を示すためにモデルが使用できる start タグと end タグを指定します。プロンプトに次のような行を追加します。

calc_prompt_template = """
You are an expert at solving word problems. Here's a question:

{question}

-------------------

When solving this problem, use the calculator for any arithmetic.

To use the calculator, put an expression between <calc></calc> tags.
The answer will be printed after the </calc> tag.

For example: 2 houses  * 8 cats/house = <calc>2 * 8</calc> = 16 cats

-------------------

Work through it step by step, and show your work.
One step per line.

Your solution:
"""

calc_prompt = calc_prompt_template.format(question=question)

モデルがこの「計算ツール」の出力にアクセスできるようにするには、生成を一時停止して結果を挿入する必要があります。stop_sequences 引数を使用して、</calc> タグで停止します。

completion = generate_text(
    model=model,
    prompt=calc_prompt,
    stop_sequences=["</calc>"],
    # The maximum length of the response
    max_output_tokens=800,
    candidate_count=1,
)

result = completion.result
print(result)
In each house, there are <calc>31 * 14

stop_sequence は結果に含まれません。式を分割し、計算機に当てはめて結果に追加します。

# Use re to clear units from the calculator expressions
import re
# Use numexpr since `eval` is unsafe.
import numexpr


def calculator(result):
  result, expression = result.rsplit('<calc>', 1)

  # Strip any units like "cats / house"
  clean_expression = re.sub("[a-zA-Z]([ /a-zA-Z]*[a-zA-Z])?",'', expression)

  # `eval` is unsafe use numexpr
  result = f"{result}<calc>{expression}</calc> = {str(numexpr.evaluate(clean_expression))}"
  return result
print(calculator(result))
In each house, there are <calc>31 * 14</calc> = 434

これをプロンプトに追加してモデルを再度実行し、中断したところから再開できるようにします。

continue_prompt=calc_prompt +"\n"+ "-"*80 + "\n" + calculator(result)

completion = generate_text(
    model=model,
    prompt=continue_prompt,
    stop_sequences=["</calc>"],
    # The maximum length of the response
    max_output_tokens=800,
    candidate_count=1,
)

print(completion.result)
mittens.
In each house, there are <calc>31 * 6

今度は、モデルは前回の計算のテキストを引き継いで次の計算に進みます。これをループで実行して、単語の問題を完全に解きます。

def solve(question=question):
  results = []

  for n in range(10):
    prompt = calc_prompt_template.format(question=question)

    prompt += " ".join(results)

    completion = generate_text(
        model=model,
        prompt=prompt,
        stop_sequences=["</calc>"],
        # The maximum length of the response
        max_output_tokens=800,
    )

    result = completion.result
    if '<calc>' in result:
      result = calculator(result)

    results.append(result)
    print('-'*40)
    print(result)
    if str(answer) in result:
      break
    if "<calc>" not in  result:
      break

  is_good = any(str(answer) in r for r in results)

  print("*"*100)
  if is_good:
    print("Success!")
  else:
    print("Failure!")
  print("*"*100)

  return is_good
solve(question);
----------------------------------------
The total number of cats is <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
The total number of mittens is <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
The total amount of yarn needed for the mittens is <calc>33418 * 141</calc> = 4711938
----------------------------------------
m.
The total number of hats is <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
 The total amount of yarn needed for the hats is <calc>14322 * 55</calc> = 787710
----------------------------------------
m.
In total, <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!

これを数回実行して解決率を見積もることができます。

good = []

for n in range(10):
  good.append(solve(question))
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
They need <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
The mittens need <calc>33418 * 141</calc> = 4711938
----------------------------------------
m of yarn.
They need <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
The hats need <calc>14322 * 55</calc> = 787710
----------------------------------------
m of yarn.
 They need a total of <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
So for the mittens, we need <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
That means we need <calc>33418 * 141</calc> = 4711938
----------------------------------------
m of yarn for mittens.
For the hats, we need <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
That means we need <calc>14322 * 55</calc> = 787710
----------------------------------------
m of yarn for hats.
 In total we need <calc>787710 + 4711938</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
In the 77 houses I have <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
They need <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
The mittens need <calc>33418 * 141</calc> = 4711938
----------------------------------------
m of yarn.
They need <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
The hats need <calc>14322 * 55</calc> = 787710
----------------------------------------
m of yarn.
 So, in total I need <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
The number of cats is <calc>77 * 31</calc> = 2387
----------------------------------------
. Each cat needs <calc>14 * 141</calc> = 1974
----------------------------------------
m of yarn for mittens. So we need <calc>1974 * 2387</calc> = 4711938
----------------------------------------
m of yarn for mittens. Each cat needs <calc>6 * 55</calc> = 330
----------------------------------------
m of yarn for hats. So we need <calc>330 * 2387</calc> = 787710
----------------------------------------
m of yarn for hats. So in total we need <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
Each cat needs <calc>14 * 141</calc> = 1974
----------------------------------------
yarn for mittens.
All cats need <calc>2387 * 1974</calc> = 4711938
----------------------------------------
yarn for mittens.
Each cat needs <calc>6 * 55</calc> = 330
----------------------------------------
yarn for hats.
All cats need <calc>2387 * 330</calc> = 787710
----------------------------------------
yarn for hats.
 All in all, you need <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
Each cat needs <calc>14 + 6</calc> = 20
----------------------------------------
items.
So we need <calc>20 * 2387</calc> = 47740
----------------------------------------
items in total.
Each mitten needs <calc>141</calc> = 141
----------------------------------------
m of yarn.
So all the mittens need <calc>141 * 47740</calc> = 6731340
----------------------------------------
m of yarn.
 Each hat needs <calc>55</calc> = 55
----------------------------------------
m of yarn.
So all the hats need <calc>55 * 47740</calc> = 2625700
----------------------------------------
m of yarn.
 In total, we need <calc>6731340 + 2625700</calc> = 9357040
----------------------------------------
m of yarn. There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
Each cat needs <calc>14 + 6</calc> = 20
********************************************************************************
Failure!
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
There are <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
There are <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
There was <calc>141 * 33418</calc> = 4711938
----------------------------------------
m of yarn needed for mittens.
There was <calc>55 * 14322</calc> = 787710
----------------------------------------
m of yarn needed for hats.
 So there was <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
There are <calc>77 * 31</calc> = 2387
----------------------------------------
cats in total. 
They need <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens. 
That's <calc>33418 * 141</calc> = 4711938
----------------------------------------
meters of yarn for mittens. 
They need <calc>2387 * 6</calc> = 14322
----------------------------------------
hats. 
That's <calc>14322 * 55</calc> = 787710
----------------------------------------
meters of yarn for hats. 
So, they need <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
There are 77 houses * 31 cats / house = <calc>77 * 31</calc> = 2387
----------------------------------------
cats.
So we need <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens.
So we need <calc>33418 * 141</calc> = 4711938
----------------------------------------
m of yarn for mittens.
So we need <calc>2387 * 6</calc> = 14322
----------------------------------------
hats.
 So we need <calc>14322 * 55</calc> = 787710
----------------------------------------
m of yarn for hats.
In total, we need <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
----------------------------------------
In total there are 77 houses * 31 cats / house = <calc>77 * 31</calc> = 2387
----------------------------------------
cats. In total 2387 cats * 14 mittens / cat = <calc>2387 * 14</calc> = 33418
----------------------------------------
mittens. In total 33418 mittens * 141m / mitten = <calc>33418 * 141</calc> = 4711938
----------------------------------------
m of yarn for mittens. In total 2387 cats * 6 hats / cat = <calc>2387 * 6</calc> = 14322
----------------------------------------
hats. In total 14322 hats * 55m / hat = <calc>14322 * 55</calc> = 787710
----------------------------------------
m of yarn for hats. In total we need 4711938 m of yarn for mittens + 787710 m of yarn for hats = <calc>4711938 + 787710</calc> = 5499648
********************************************************************************
Success!
import numpy as np
np.mean(good)
0.9