Langchain の CSV Agent で CSV データを自動分析してみた

先日　Azure OpenAI の Assistant 機能の一つ Code Interpreter で CSV データを分析した内容をまとめた投稿をしました。
[Azure OpenAI の Code Interpreter で CSV データを分析してみた](URL "https://qiita.com/kkubo124/items/353017333ff956fdfa3e")

今回は Langchain の CSV Agent 機能を使って、サンプルの CSV ファイルの内容について質問回答させるような仕組みを作りました。
手短に手順と結果を書きます。

## 全体ソースコード
Azure Functions で実装をしました。
```python
import azure.functions as func
from openai import AzureOpenAI
from langchain_community.chat_models import AzureChatOpenAI
from langchain_experimental.agents.agent_toolkits import create_csv_agent
from langchain.agents.agent_types import AgentType
import os
import json
import time

@app.route(route="csv_analyzer_langchain", auth_level=func.AuthLevel.FUNCTION)
def csv_analyzer_langchain(req: func.HttpRequest) -> func.HttpResponse:
    llm = AzureChatOpenAI(
        api_key=os.environ.get("AzureOpenAI.ApiKey"),
        openai_api_version=os.environ.get("AzureOpenAI.ApiVersion"),
        azure_endpoint=os.environ.get("AzureOpenAI.Endpoint"),
        azure_deployment=os.environ.get("AzureOpenAI.ModelName")
    )

    csv_file = "sample.csv"
    csv_agent = create_csv_agent(
        llm,
        csv_file,
        verbose=True,
        agent_type=AgentType.OPENAI_FUNCTIONS,
        allow_dangerous_code=True
    )

    req_body = req.get_json()
    question = req_body.get("question")
    answer = csv_agent.run(question)

    data = {
        "answer": answer
    }

    return func.HttpResponse(
        json.dumps(data),
        status_code=200,
        mimetype="application/json"
    )
```

## 準備
### Azure OpenAI
Azure OpenAI のモデルを Langchain 内で使用するので、事前にモデルをデプロイしておきます。
今回は、GPT-4o (2024-05-13) をデプロイし使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409268/0acf7123-4031-0ce0-e216-441dd9d99209.png)

### Python
必要な Python モジュールです。
```text:requirements.txt
azure-functions
openai
langchain
langchain_experimental
langchain_community
pandas
tabulate
```
サンプルの CSV は以下のようなものを用意しました。
```text:sample.csv
Id	Category	Description
1	アクション	元特殊部隊員の男がテロ組織に濡れ衣を着せられる。命を狙われながらも真実を暴き出そうとする。
2	アクション	環境活動家が動物保護の証拠を握り、武装組織に追われながら広大な砂漠を生き抜く壮絶な物語。
3	アクション	地下都市の独裁者に抗う少女が、仲間と共に危険な罠に挑み、自由を取り戻すため戦いを繰り広げる。
4	アクション	世界を壊滅させる兵器がテロ組織の手に渡る。秘密部隊が極限状態で兵器奪還を試みるアクション大作。
5	アクション	孤独な自警団の男が、都市を脅かす謎のテロリスト集団と戦い、過去の因縁と向き合っていく。
6	恋愛	高校時代に別れた初恋相手と再会した主人公。成長した二人が再び心を通わせ、過去を乗り越えていく。
7	恋愛	離れた国で暮らす恋人同士が、手紙やビデオ通話を通じて愛を育む中、思わぬ試練が二人を待ち受ける。
8	恋愛	人気パティシエの女性が経営危機のカフェを救う中、不器用な青年と恋に落ちる温かなラブストーリー。
9	恋愛	雨宿りで出会った二人が同じ日に再会する約束を重ね、少しずつ恋心が芽生える純粋なラブストーリー。
10	恋愛	敵対する家に生まれた青年と女性が、抗えない運命に翻弄されながらも愛を貫こうとする切ない物語。
11	ホラー	謎の失踪事件が起きる森でキャンプを始めた若者たち。次々と恐怖の現象に襲われ、生存を賭けた戦いが始まる。
12	ホラー	古びた屋敷の鏡が異世界への扉だった。そこに潜む邪悪な存在が現実に侵食し、住人たちを脅かす。
13	ホラー	山奥の廃村で起きた忌まわしい事件を調査する記者。徐々に過去の呪いが解き放たれ、恐怖が襲う。
14	ホラー	肝試しに訪れた廃校で閉じ込められた学生たち。見えない何かが迫りくる中、脱出の手段を探る。
15	ホラー	隣人が忽然と姿を消し、不気味な音が聞こえる部屋。調査を始めた女性が恐ろしい真相にたどり着く。

```

## やってみた
Azure Functions を起動させ、リクエストをなげます。

質問：ホラーのカテゴリーの件数を教えてください
回答：ホラーのカテゴリーの件数は5件です。🎉🎉
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409268/0d36f84d-bb62-a700-61dc-68c9c6d8aba1.png)

上手く回答が返りました。

## さいごに
Azure OpeAI の Assistants API（※2024/12/14 時点でプレビュー）の Code Interpreter も同様に CSV の内容を AI モデルに読み込ませて回答させることは可能ですが、使用する AI モデルがリージョンごとに制限があったりするなど確認しないといけない面倒な部分があります。Langchain の CSV Agent では特に制限がないので簡単に実装ができました。

[Azure OpenAI アシスタント コード インタープリター](URL "https://learn.microsoft.com/ja-jp/azure/ai-services/openai/how-to/code-interpreter?tabs=python")

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409268/57272c83-2ea5-e30b-a6c1-ab24a9a984e4.png)
[Azure OpenAI Service モデル : アシスタント（プレビュー）]("https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/models?tabs=python-secure%2Cglobal-standard%2Cstandard-chat-completions#assistants-preview")

Assistants API の使い勝手がよくなっていくのであれば、こちらを優先的に使っていきたいです。