BigQuery DataFramesを試す

# 1.はじめに
* 最近使えるようになった[BigQuery Data Frames](https://cloud.google.com/python/docs/reference/bigframes/latest)を試し。
* 後ろではBigQueryが処理を行ってくれているので、レコード数が多くてもサクッと処理してもらえる。
* MLやPaLM2との連携が簡単なので、今までBigQueryとpandas(polars)で連携してやってきた処理が代替できそう。

# 2.参考情報
* 下記のように、概要からMLまではすでに紹介されているので、自前のデータでPaLM2との連携部分を試してみた。
[公式](https://github.com/googleapis/python-bigquery-dataframes)
[BigQuery DataFramesを使ってみる](https://dev.classmethod.jp/articles/bigquery_df/)
[Google launches BigQuery Data Frames](https://medium.com/codex/google-launches-bigquery-data-frames-762ae20ff1d0)


# 3. PaLM2による固有表現抽出
* 使ったのは、蓄積しているテクノロジー系のニュース。

```python
!pip3 install --upgrade bigframes
import bigframes.pandas as bpd

bpd.reset_session()
bpd.options.bigquery.project = "****"
df1 = bpd.read_gbq("****.techchurchnews.dailynews3")
df1
```

こんな感じで確かにpandasの処理に似てて楽です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/509bab18-5aad-ea26-bd73-0f026cd16c1f.png)


* ここから公式ページなどを見て実行していく。

```python
import bigframes.ml.llm as llm

palm2generator = llm.PaLM2TextGenerator(
connection_name="****",
)

```

とやると、エラーが出てしまう。公式ではproject-idを指定すればいいような書きっぷりだったけど。。

```python
ValueError: connection_name must be of the format <PROJECT_NUMBER/PROJECT_ID>.<LOCATION>.<CONNECTION_ID>, got ****.
```



`<CONNECTION_ID>`ってなんだ？となって、調べた結果、[ここ](https://cloud.google.com/bigquery/docs/reference/bigqueryconnection#client-libraries-install-python)を参考しつつ下記のように発見。

```python
from google.cloud import bigquery_connection_v1 as bq_connection
def main(
    project_id: str = "your-project-id", location: str = "US", transport: str = "grpc"
) -> None:
    """Prints details and summary information about connections for a given admin project and location"""
    client = bq_connection.ConnectionServiceClient(transport=transport)
    print(f"List of connections in project {project_id} in location {location}")
    req = bq_connection.ListConnectionsRequest(
        parent=client.common_location_path(project_id, location)
    )
    for connection in client.list_connections(request=req):
        print(f"\tConnection {connection.friendly_name} ({connection.name})")

main(project_id="****",location="US")

```

```python
main(project_id="****",location="US")
List of connections in project **** in location US
	Connection  (projects/**/locations/us/connections/{~~})
```
この~~の部分をconnectionに設定すればいいと判明して使う。


```
import bigframes.ml.llm as llm

palm2_text_generator = llm.PaLM2TextGenerator(
    connection_name="****.US.~~",
)

```

これでpalm2_text_generatorができるので、[ここ](https://cloud.google.com/python/docs/reference/bigframes/latest/bigframes.ml.llm.PaLM2TextGenerator)を参照しつつprompt列を作成。

```python
df1["prompt"] = "Please extract the named entity:" + df1["title"]
df1["prompt"]

palm2_text_generator.predict(df1[["prompt"]])
```

実行結果のjobを開くとこのような感じ（ml_generate_text_llm_result部分）。一部言うことを聞いてくれてない様子だけど、promptの工夫でどうにかできるのではないかと検討中。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/855edb4a-ecd0-754d-ef3a-a4b11d78f92d.png)



# 4.その他　
* なお、PalM2のembedding表現を取得したい場合は

```python
palm2embedder = llm.PaLM2TextEmbeddingGenerator(
    connection_name="****.US.~~",
)
```

で

```python
palm2embedder.predict(df1["title"])
```
と実行すればOK。こちらも１分間の実行制限に注意しつつ使えば、便利。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/ada85248-8f8e-9a2b-b8b0-eef5d25c9dc2.png)