BigQueryのデータに日本語でQAしてみよう
LangChainとVertexAIを用いて、日本語でデータを呼び出します。
Table of contents
author: Chiakoba
はじめに
DataチームのChiaKobaです。
AIのニュースで溢れる毎日ですね。 ChatGPTの話題は毎日絶えないですね。
Vertex AIも忘れないで。
ということで、今回は、VertexAIの生成AIモデルと言語モデルのフレームワーク「LangChain🦜⛓️」を使って、BigQueryのデータを日本語で呼び出してみます。
VertexAIの生成 AI モデル
VertexAIで利用可能な生成 AI モデルは、以下のようなコンテンツに対してモデルがあります。
- text
- chat
- image(写真やPDFなど)
- code
- video
- embeddings(単語や文といった自然言語の情報を、その単語や文の意味を表現するベクトル空間に配置)
今回は、textのモデルを使います。 また、Vertex AIでは、これらのモデルが呼び出せるようPaLM APIとしてエンドポイントを用意しています。
(ChatGPTのAPIと同じように呼べます!)
言語モデルのフレームワーク
LangChainは、大規模言語モデル(LLM)を用いてアプリケーションを効率よく開発するためのフレームワークです。
言語モデルが単体だとどうしても難しい、面倒な処理になるといった問題を少ない実装で可能にしてくれるありがたいインコ🦜様です。
大きく2つ特徴があります。
- 特定の用途(社内の情報を突っ込みたい!等)へ特化した機能を提供する
- LLMを利用したアプリケーション開発に必要な部品を抽象化したモジュールとして提供する
今回は、SQLと対話する機能を使っていきます。
これからも注目していきたいフレームワークです。
方法
今回はColaboratoryを利用して、Pythonを使って、実際に試していきます。
準備
1. まず、GCPのBigQueryとVertexAIのAPIを有効化します。 GCPコンソールやCloudSDKで有効化しておきましょう。
gcloud services enable aiplatform.googleapis.com bigquery.googleapis.com
2. 次は、Colaboratoryで認証です。GCPコンソールで自分に権限があることは確認しておきましょう。
from google.colab import auth as google_auth
google_auth.authenticate_user()
3. Colaboratoryで必要なパッケージをインストールします。この時、「RESTART RUNTIME」ボタンを押してランタイムを再起動します。
!pip install langchain sqlalchemy-bigquery google-cloud-bigquery google-cloud-aiplatform
実装
今回は、SQLAlchemyを使って、BigQueryのデータをLangChainで処理します。
テストデータは個人情報テストデータジェネレーターで作りました。
Colaboratoryでソースを実行していきます。
from google.cloud import bigquery
from sqlalchemy import *
from langchain.llms import VertexAI
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
import vertexai
# 自分の環境に合わせて変更
dataset = "DATASET_NAME" # @param {type:"string"}
project_id= "PROJECT_ID" # @param {type:"string"}
sqlalchemy_url = f"bigquery://{project_id}/{dataset}"
vertexai.init(project=project_id, location="us-central1")
# SQLAlchemy エンジンにBigQueryのデータの場所を設定
db = SQLDatabase.from_uri(database_uri=sqlalchemy_url)
# Vertex AI 基盤モデルを設定(ほとんどデフォルト)
llm = VertexAI(
model_name="text-bison@001",
max_output_tokens=1024,
temperature=0.1,
top_p=0.8,
top_k=40,
verbose=True,
)
# SQL データベースと対話するエージェントへSQLとLLMを設定
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
agent_executor = create_sql_agent(
llm=llm,
toolkit=toolkit,
verbose=True,
top_k=10,
)
def run_answer(query):
res = agent_executor.run(query)
return res
実行!
run_answer("女性の人数を教えてください。")
以下がOutputです。
詳細を見る
> Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input:
Observation: test_personal_info
Thought:I found the table test_personal_info. I should query the schema of this table to see what columns I can use in my query.
Action: sql_db_schema
Action Input: test_personal_info
Observation:
CREATE TABLE `test_personal_info` (
`full_name` STRING,
`full_name_hiragana` STRING,
`age` INT64,
`birthdate` DATE,
`sex` STRING,
`blood_type` STRING,
`email_address` STRING,
`phone_number` STRING,
`mobile_phone_number` STRING,
`postal_code` STRING,
`address` STRING,
`company_name` STRING,
`credit_card` STRING,
`expiration_date` STRING,
`my_number` STRING
)
/*
3 rows from test_personal_info table:
full_name full_name_hiragana age birthdate sex blood_type email_address phone_number mobile_phone_number postal_code address company_name credit_card expiration_date my_number
中原 義人 なかはら よしと 79 1944-02-27 男 A yoshitonakahara@example.com 0735-21-4394 050-6374-8793 647-9731 和歌山県橋本市城山台4-1-6 4605270111483780 04/25 607754886619
新海 誠子 しんかい せいこ 79 1944-03-10 女 A shinkai_seiko@example.org 0438-78-1600 080-5900-1396 289-3898 千葉県船橋市西船3-1-9 5314247057138833 07/27 949472424688
野田 洋一 のだ よういち 79 1944-07-26 男 A youichinoda@example.com 0256-22-5571 080-5818-6411 956-6982 新潟県新潟市中央区関屋田町3-3-17ジョイフル216 3576355852349410 10/26 224409039958
*/
Thought:I found the column sex in the table test_personal_info. I can use this column to count the number of females.
Action: sql_db_query
Action Input: SELECT COUNT(*) FROM test_personal_info WHERE sex = '女'
Observation: [(167,)]
Thought:I now know the final answer
Final Answer: 女性の人数は167人です。
> Finished chain.
女性の人数は167人です。
しっかりテーブル構造を把握して、型もBigQueryと一致しています。 そして、SQLを作成し、最終行にちゃんと答えが…!SQLも正しそうですね。
念の為、本当に合ってるかBigQueryにSQL投げてみましょう!
client = bigquery.Client(project=project_id)
# 実行するクエリ
query = """
SELECT
COUNT(*) as cnt
FROM test.test_personal_info WHERE sex = '女'
;
"""
df = client.query(query).to_dataframe()
df.head()
合ってました!
ちょっと複雑な質問をしてみます。
run_answer("平均年齢より高い今月が誕生日の女性の誕生月と名前を3人教えてください")
結果どーん。
詳細を見る
> Entering new AgentExecutor chain...
Action: sql_db_list_tables
Action Input:
Observation: test_personal_info
Thought:I found the table test_personal_info. I should query the schema of this table to see what columns I can use in my query.
Action: sql_db_schema
Action Input: test_personal_info
Observation:
CREATE TABLE `test_personal_info` (
`full_name` STRING,
`full_name_hiragana` STRING,
`age` INT64,
`birthdate` DATE,
`sex` STRING,
`blood_type` STRING,
`email_address` STRING,
`phone_number` STRING,
`mobile_phone_number` STRING,
`postal_code` STRING,
`address` STRING,
`company_name` STRING,
`credit_card` STRING,
`expiration_date` STRING,
`my_number` STRING
)
/*
3 rows from test_personal_info table:
full_name full_name_hiragana age birthdate sex blood_type email_address phone_number mobile_phone_number postal_code address company_name credit_card expiration_date my_number
川口 健人 かわぐち けんと 20 2003-06-30 男 A kento_kawaguchi@example.co.jp 03-0270-0744 050-4668-9355 163-1228 東京都世田谷区上馬1-1-13 株式会社大創 374645581027174 02/28 143103840908
早川 しげる はやかわ しげる 20 2003-02-06 男 A shigeruhayakawa@example.jp 03-9293-0204 090-2502-0159 192-0658 東京都世田谷区砧2-1-17 有限会社伊藤 3581172691900144 08/25 582489059338
石井 優次 いしい ゆうじ 20 2003-08-12 男 A yuujiishii@example.jp 03-2810-0549 080-4006-4329 191-4966 東京都江戸川区西小岩3-3-9オリエント704 株式会社クロノス 3538837989454830 06/26 607214136580
*/
Thought:The question is asking for the birth month and name of women whose age is higher than the average age. I need to find the average age of all people in the table.
Action: sql_db_query
Action Input: SELECT AVG(age) FROM test_personal_info
Observation: [(50.795999999999985,)]
Thought:The average age is 50.795999999999985. I need to find all women whose age is higher than this.
Action: sql_db_query
Action Input: SELECT birth_month, full_name FROM test_personal_info WHERE sex = '女' AND age > 50.795999999999985 ORDER BY birth_month LIMIT 3
Observation: Error: (google.cloud.bigquery.dbapi.exceptions.DatabaseError) 400 Unrecognized name: birth_month at [1:8]
Location: US
Job ID: 8d9d112d-a269-45ff-92e8-4d0439cd1f78
[SQL: SELECT birth_month, full_name FROM test_personal_info WHERE sex = '女' AND age > 50.795999999999985 ORDER BY birth_month LIMIT 3]
(Background on this error at: https://sqlalche.me/e/14/4xp6)
Thought:The birth_month column does not exist in the table. I need to find the column that contains the birth month.
Action: sql_db_schema
Action Input: test_personal_info
Observation:
CREATE TABLE `test_personal_info` (
`full_name` STRING,
`full_name_hiragana` STRING,
`age` INT64, ,
`birthdate` DATE
`sex` STRING,
`blood_type` STRING,
`email_address` STRING,
`phone_number` STRING,
`mobile_phone_number` STRING,
`postal_code` STRING,
`address` STRING,
`company_name` STRING,
`credit_card` STRING,
`expiration_date` STRING,
`my_number` STRING
)
/*
3 rows from test_personal_info table:
full_name full_name_hiragana age birthdate sex blood_type email_address phone_number mobile_phone_number postal_code address company_name credit_card expiration_date my_number
川口 健人 かわぐち けんと 20 2003-06-30 男 A kento_kawaguchi@example.co.jp 03-0270-0744 050-4668-9355 163-1228 東京都世田谷区上馬1-1-13 株式会社大創 374645581027174 02/28 143103840908
早川 しげる はやかわ しげる 20 2003-02-06 男 A shigeruhayakawa@example.jp 03-9293-0204 090-2502-0159 192-0658 東京都世田谷区砧2-1-17 有限会社伊藤 3581172691900144 08/25 582489059338
石井 優次 いしい ゆうじ 20 2003-08-12 男 A yuujiishii@example.jp 03-2810-0549 080-4006-4329 191-4966 東京都江戸川区西小岩3-3-9オリエント704 株式会社クロノス 3538837989454830 06/26 607214136580
*/
Thought:The birthdate column contains the birth month. I need to extract the birth month from the birthdate column.
Action: sql_db_query
Action Input: SELECT EXTRACT(MONTH FROM birthdate) AS birth_month, full_name FROM test_personal_info WHERE sex = '女' AND age > 50.795999999999985 ORDER BY birth_month LIMIT 3
Observation: [(1, '朝比奈 千香子'), (1, '藤田 裕子'), (1, '萩田 あやめ')]
Thought:I found the birth month and name of women whose age is higher than the average age.
Action: sql_db_query_checker
Action Input: SELECT EXTRACT(MONTH FROM birthdate) AS birth_month, full_name FROM test_personal_info WHERE sex = '女' AND age > 50.795999999999985 ORDER BY birth_month LIMIT 3
Observation: SELECT EXTRACT(MONTH FROM birthdate) AS birth_month, full_name FROM test_personal_info WHERE sex = '女' AND age > 50.795999999999985 ORDER BY birth_month LIMIT 3
Thought:I now know the final answer
Final Answer: 1月: 朝比奈 千香子, 藤田 裕子, 萩田 あやめ
> Finished chain.
1月: 朝比奈 千香子, 藤田 裕子, 萩田 あやめ
今月は11月です。今月というところは読み取れなかったですね。
でもかなり惜しい、月まで求められてるし、人数も読み取れてる。いいポイントまで行ってます。 あと個人的には最初、エラーになっても諦めないところ、好きです。
もう少し情報を与えれば、回答まで導けそうです。
このような質問をする必要があるなら、もう少し人間が考える必要がありますね。
まとめ
Vertex AIとLangChainを使って、日本語でデータベースと簡単なお話ならできることが分かりました。
感動しちゃいます、どんどんすごい時代になっていますね…!!
LangChainに興味を持つとてもいい機会になりました。
最後まで読んでくださったあなた、ありがとうございます。
参考
https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text
GI Cloudは事業の拡大に向けて一緒に夢を追う仲間を募集しています
当社は「クラウドで日本のIT業界を変革し、世の中をもっとハッピーに」をミッションに掲げ、Google Cloudに特化した技術者集団として、お客様にコンサルティングからシステム開発、運用・保守まで一気通貫でサービスを提供しています。
まだ小規模な事業体ですが、スタートアップならではの活気と成長性に加えて、大手総合商社である伊藤忠グループの一員としてやりがいのある案件にもどんどんチャレンジできる環境が整っています。成長意欲の高い仲間と共にスキルを磨きながら、クラウドの力で世の中をもっとハッピーにしたい。そんな我々の想いに共感できる方のエントリーをお待ちしています。
※本記事は、ジーアイクラウド株式会社の見解を述べたものであり、必要な調査・検討は行っているものの必ずしもその正確性や真実性を保証するものではありません。
※リンクを利用する際には、必ず出典がGIC dryaki-blogであることを明記してください。
リンクの利用によりトラブルが発生した場合、リンクを設置した方ご自身の責任で対応してください。
ジーアイクラウド株式会社はユーザーによるリンクの利用につき、如何なる責任を負うものではありません。