📘
guidanceでgoogle custom search api試してみた
はじめに
Microsoftが開発されたguidanceを少し触ってみたメモです。
langchainだと自分の思うようにコントロールできないことが多かったので、guidanceだとその辺り解決するのかなぁと思って今回検証してみました。
今回検証してみたコードはこちらのリポジトリにまとめております。
やったことは、
- guidanceの動かし方の検証
- guidanceからgoogle searchができるかどうかの検証
です。
guidanceの公式サンプルにbing searchを使った実装例があったのでそれを参考にしています。
準備
- OpenAI API Keyの取得
- google custom searchの設定・Key取得
- この辺りはこのサイトを参考にさせていただきました。
- .envの用意
OPENAI_API_KEY="" GOOGLE_CUSTOM_SEARCH_API_KEY="" CUSTOM_SEARCH_ENGINE_ID=""
- 検証環境の用意
- ライブラリのインストール
pyenv local 3.10.9 python -m venv venv venv/Script/activate (venv)pip install guidance==0.0.61 jupyterlab python-dotenv
- ライブラリのインストール
実装について
今回はノートブックで実装しました。
ライブラリとAPI KEYを設定
import os
import guidance
import requests
from dotenv import load_dotenv
load_dotenv()
GOOGLE_CUSTOME_SEARCH_API_KEY=os.getenv("GOOGLE_CUSTOM_SEARCH_API_KEY")
GOOGLE_CUSTOME_SEARCH_ENGINE_ID=os.getenv("CUSTOM_SEARCH_ENGINE_ID")
GOOGLE_CUSTOME_SEARCH_BASE_URL = "https://www.googleapis.com/customsearch/v1"
Google Search周りを実装
top=n件の検索結果を[{"title": "", "snippet": ""}, ...]として返すように実装
def google_search(search_term: str, num: int = 3) -> dict:
params = {
'q': search_term,
'key': GOOGLE_CUSTOME_SEARCH_API_KEY,
'cx': GOOGLE_CUSTOME_SEARCH_ENGINE_ID,
'num': num,
}
response = requests.get(GOOGLE_CUSTOME_SEARCH_BASE_URL, params=params)
return response.json()["items"]
def get_top_snippets(query: str, n: int = 3):
results = google_search(query, num=n)[:n]
return [{'title': x['title'], 'snippet': x['snippet']} for x in results]
guidanceの実装
検索するか否か判定する関数と、検索関数を実装
def is_search(completion: str) -> bool:
return '<search>' in completion
def search(query: str) -> dict:
return get_top_snippets(query)
assistantの回答が事実に依存する場合はsearch関数を使うように指示
guidance.llm = guidance.llms.OpenAI("gpt-3.5-turbo")
prompt = guidance('''{{#system~}}
あなたは親切なアシスタントです。
{{~/system}}
{{#user~}}
今後、あなたの回答が事実関係に依存する場合は、回答前に<search>query</search>という機能でウェブを検索してください。そうすれば、私がウェブ検索結果を貼り付けますので、あなたはそれに答えることができます。
{{~/user}}
{{#assistant~}}
わかりました、そうさせていただきます。
{{~/assistant}}
{{#user~}}
さぁ始めましょう!
{{~/user}}
{{#assistant~}}
よし、準備OKだ。
{{~/assistant}}
{{#user~}}
{{user_query}}
{{~/user}}
{{#assistant~}}
{{gen "query" stop="</search>"}}{{#if (is_search query)}}</search>{{/if}}
{{~/assistant}}
{{#if (is_search query)}}
{{#user~}}
Search results: {{#each (search query)}}
<result>
{{this.title}}
{{this.snippet}}
</result>{{/each}}
{{~/user}}
{{#assistant~}}
{{gen "answer"}}
{{~/assistant}}
{{/if}}''')
試す
天気を聞いてみる
query = "今日の大阪の天気は?"
p1 = prompt(user_query=query, search=search, is_search=is_search)
p1
おわりに
今回はguidanceのサンプルを見ながら、ユーザーからの質問のリファレンスとしてGoogle Search APIを使うことができるかの検証を行いました。
今の実装ではlangchainの精度には程遠くはありますが、guidanceを使うと自分の任意のタイミングで処理を差し込むことができるので、かなり個人的には使いやすいと思いました。
Discussion