クローリング&スクレイピングでいい感じにRetrieve用のデータソースを作ることが出来ないかを考えてみる。
モチベーションとしては、一々Webページをダウンロードして保存して、読み込んで、とかやるのが面倒だったので、URLだけ投げれば自動的によしなにしてくれる仕組みがあるといいなぁというところ。
公式DocにはHTMLもローディング出来るよ~とあったので、BSHTMLoaderを使えば出来るんかな?ということでやってみた。
結果としては一時的にWebページをローカルファイルに保存しないと動作はしなかったが、データの参照場所はWeb上のURLを指定することが出来た。結構無理やりだけど。
https://python.langchain.com/docs/modules/data_connection/document_loaders/html
元となるデータについて
Googleのベストプラクティス集を使います。
https://cloud.google.com/compute/docs/regions-zones/global-regional-zonal-resources?hl=ja
このページをまるっと取ってくると無駄な部分がたくさんあるので、「フィードバックを送信」のボタンで囲まれている部分だけを取ってきてデータソースにしたい。
NGパターン
URLを渡せばよしなにやってくれるかな・・・?と思い、URLをメソッドに投げてみましたが、あえなく撃沈。
完璧ローカルのファイルを読みに行ってるよ、これ・・・。まぁAPIを見たときからひしひしと感じてはいたけど。
url = 'https://cloud.google.com/compute/docs/regions-zones/global-regional-zonal-resources?hl=ja'
loader = BSHTMLLoader(url)
loader.load()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[36], line 3
1 url = 'https://cloud.google.com/compute/docs/regions-zones/global-regional-zonal-resources?hl=ja'
2 loader = BSHTMLLoader(url)
----> 3 loader.load()
File ~/anaconda3/envs/llm/lib/python3.10/site-packages/langchain/document_loaders/html_bs.py:48, in BSHTMLLoader.load(self)
45 """Load HTML document into document objects."""
46 from bs4 import BeautifulSoup
---> 48 with open(self.file_path, "r", encoding=self.open_encoding) as f:
49 soup = BeautifulSoup(f, **self.bs_kwargs)
51 text = soup.get_text(self.get_text_separator)
FileNotFoundError: [Errno 2] No such file or directory: 'https://cloud.google.com/compute/docs/regions-zones/global-regional-zonal-resources?hl=ja'
データの前処理
ということで、一番最初に書いたモチベーションは叶わずだったけど、見かけ上はなんとかしてWebがソースなんだよということが分かるようにしてみたい。
かなり雑だけど、まずは必要な部分だけを抜き出してファイルに保存する前処理。
url = 'https://cloud.google.com/compute/docs/regions-zones/global-regional-zonal-resources?hl=ja'
response = requests.get(url)
start_text = "フィードバックを送信"
content = response.text
start_index = content.find(start_text)
end_index = content.find(start_text,start_index + 1)
extracted_content = content[start_index:end_index].strip()
with open(f'./langchain_test/test1.html',mode='w') as file:
file.write(extracted_content.replace("\n",""))
こんな感じのファイルが出来上がる。
htmlファイルの処理とデータソースの書き換え
あとはlangchainを使ってhtmlを処理して、無理やりデータの中身を書き換えるだけ。
loader = BSHTMLLoader(file_path = './langchain_test/test1.html')
datasource = loader.load()
datasource
----------------------------------------------------------------------------------------------------------
[Document(page_content='フィードバックを送信 グローバル リソース、リージョン リソース、ゾーンリソース
コレクションでコンテンツを整理 必要に応じて、
コンテンツの保存と分類を行います。 このドキュメントでは、Compute Engine のグローバル リソース、
リージョン リソース、ゾーンリソースについて説明します。Google Cloud のリソースは世界中の複数のロケーションで
ホストされています。これらのロケーションは、リージョンと、そのリージョン内のゾーンで構成されています。
リージョン内の異なるゾーンにリソースを置くことで、インフラストラクチャ、ハードウェア、ソフトウェアにさまざまな
種類の障害が発生した場合に、その障害を切り離すことができます。複数のリージョンにリソースを置けば、障害からの隔
離をさらに強化できます。複数の障害発生ドメインにリソースを分散させることで、堅牢なシステムを設計できます。
(中略)
metadata={'source': './langchain_test/test1.html', 'title': ''})]
このmetadataの中身を変えたい!
datasource[0].metadata['source'] = 'https://cloud.google.com/architecture/best-practices-for-operating-containers?hl=ja'
datasource[0].metadata['title'] = 'グローバルリソース、リージョンリソース、ゾーンリソースのベストプラクティス'
--------------------------------------------------------------------------------------------------------
(中略)
metadata={'source': 'https://cloud.google.com/architecture/best-practices-for-operating-containers?hl=ja',
'title': 'グローバルリソース、リージョンリソース、ゾーンリソースのベストプラクティス'})]
強引が過ぎますが、実現できました。
もっと簡単でいい感じのやり方があれば教えてほしいです。