🤖

自然言語でSQL生成。LangChain + Bedrock(Claude 3 Opus) + MySQL

2024/04/22に公開

環境

Mac M1 Pro Sonoma 14.4.1

概要

自然言語でSQLを生成する方法を色々調べている中で、下記のページを見つけたので、やってみることに。
https://python.langchain.com/docs/use_cases/sql/

さらにタイミング的に、BedrockでClaude 3 Opusが使えるようになったので使います。
※SQLの生成であればもっと性能の低いllmでもいいかも知れません。

サンプルコード
https://github.com/na8esin/LangChain-sample/blob/main/llm_db.py
※AWSを使用する際は sso login してます。

LangChain + Bedrock

まずは、この辺りのページを見て、bedrockを動かそうとしましたが、
https://python.langchain.com/docs/integrations/llms/bedrock/

Claude v3 models are not supported by this LLM.Please use `from langchain_community.chat_models import BedrockChat` instead.

というエラーが出るのでBedrockはBedrockChatに変更。

そのとき作ったサンプルがこちら
https://github.com/na8esin/LangChain-sample/blob/main/bedrock_chat_sample.py

SQLDatabase

次にSQLDatabaseというLangChainのツールがあるようなので、そちらを使ってみることに

https://python.langchain.com/docs/integrations/toolkits/sql_database/

↓を読むと、SQLAlchemy wrapper around a database.と書いてあります。
https://api.python.langchain.com/en/latest/utilities/langchain_community.utilities.sql_database.SQLDatabase.html

作ったサンプルがこちら
https://github.com/na8esin/LangChain-sample/blob/main/lang_chain_sql.py

最初に↑を実行した際に下記のエラーが発生しました。
ModuleNotFoundError: No module named 'MySQLdb'

これはmysqlのパッケージが足りないそうで、下記を見ながらインストールすることに
https://github.com/PyMySQL/mysqlclient/blob/main/README.md#macos-homebrew

mac自体へのmysql-clientのインストールは以前mac portsで行ったのでスキップ。

そして、mysqlclientをrequirements.txtに追加して、下記実行
pip install --upgrade -r requirements.txt

Exception: Can not find valid pkg-config name.

みたいなエラーが出てうまくいかないのでさらに、
sudo port install pkgconfig
※パッケージ名はpkgconfigだけど、インストール先はpkg-configなので注意

which pkg-config
/opt/local/bin/pkg-config

そして、さらにPKG_CONFIG_PATHを指定するようにと書いてあるので、自分の環境では↓でした。
export PKG_CONFIG_PATH="/opt/local/lib/mysql8/pkgconfig"
これで、pip installが成功するようになりました。

最後全部を組み合わせる

一番最初に出てきた、下記を実行
https://github.com/na8esin/LangChain-sample/blob/main/llm_db.py

ですが、bedrockからのレスポンスに余計な説明文がついてきてしまう。

To get the total number of products, we can run the following SQL query:

SELECT COUNT(*) AS total_products
FROM products;

ここで、langchainが生成してくれているプロンプトを
chain.get_prompts()[0].pretty_print()
で出力してみることに

You are a MySQL expert. Given an input question, first create a syntactically correct MySQL query to run, then look at the results of the query and return the answer to the input question.
Unless the user specifies in the question a specific number of examples to obtain, query for at most 5 results using the LIMIT clause as per MySQL. You can order the results to return the most informative data in the database.
Never query for all columns from a table. You must query only the columns that are needed to answer the question. Wrap each column name in backticks (`) to denote them as delimited identifiers.
Pay attention to use only the column names you can see in the tables below. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table.
Pay attention to use CURDATE() function to get the current date, if the question involves "today".

Use the following format:

Question: Question here
SQLQuery: SQL Query to run
SQLResult: Result of the SQLQuery
Answer: Final answer here

Only use the following tables:
{table_info}

Question: {input}

出力してみましたが、これをうまい具合カスタマイズする方法を調べきれなかったので、
invokeメソッドを実行する際のメッセージに
Please respond only sql. No explanation is necessary.
を追加しました。

そうするとSQLだけをレスポンスしてくれるようになって、実行できるようになりました。

しくみのテックブログ

Discussion