【ツール紹介】その生成AI、ちゃんと働いてる？OpenLITで見守ろう！！


2025/2/4 続編（OpenLITの詳細機能紹介）を執筆しました！

https://qiita.com/melhts/items/1bbfa659f9e43eae8a47

# １．はじめに
こんにちは。

私は情報システムやサービスの運用に関する研究開発を担当する部署に所属している**新人エンジニア**です。

今回は以前ご紹介したObservabilityツールの中から「**OpenLIT**」を選択して実際に触ってみました。

https://qiita.com/melhts/items/e89bbbd036659f845b9c

環境については、AWSの「EC2」上で構築しました。
また、同じくAWSの生成AIサービスである「Bedrock」も活用してみました！

本記事はIT知識ゼロの私が、**生成AIに特化したObservabilityツールであるOpenLITを導入した内容をまとめた**ものになります。

まずはOpenLITについておさらいした後に、導入方法について説明します。


# ２．OpenLITって何？
OpenLITは**生成AIアプリケーションを監視するためのOSS**です。

https://openlit.io/

近年、「**生成AI**」はビジネスや日常生活のさまざまな場面で利用されており、最も勢いのある技術といっても過言ではありません。
その生成AIを効果的に運用するには、そのパフォーマンスや問題点をリアルタイムで監視し、トラブルが発生した場合に迅速に対応する必要があります。

「**OpenLIT**」は生成AIに特化して、パフォーマンスと使用状況を追跡・分析できるObservabilityツールです。

![openlit_intro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/6fadab5d-8ec8-33cb-70a5-4602e1caabf7.png)
引用元：[OpenLITのGitHubリポジトリ](https://github.com/openlit/.github/blob/aa13929e54ea6e8756d4d4e90068c904e5e5b2ce/profile/assets/openlit-feature-banner.png)

以下に主な特徴についてまとめます。

:::note warn
本記事の情報は2024年12月時点、``v1.11.6``の情報です。
:::


## 主な特徴

### 特徴１：生成AIに特化した監視項目が用意されている
一般的なObservabilityツールとの大きな違いが**生成AIに特化している**という点です。
監視項目の一部を以下に示します。

**監視項目**
- 合計トークン数、平均トークン数
- 合計コスト、平均コスト 
- 1リクエストあたりの時間
- 使用モデル割合
- リクエストごとの詳細情報（時刻、プロンプト、リクエスト、トークン、コスト、etc.）
- エラーの発生時の詳細情報（時刻、エラー文、エラータイプ、etc.）

:::note info
生成AI以外にもベクトルDBとGPUに対してのダッシュボードも用意されています。
:::

### 特徴２：多くのLLMモデルプロバイダーに対応している
有名なLLMモデルプロバイダーである「OpenAI」や「Anthropic」はもちろん、多くのLLMモデルに対応しています。

![openlit_work.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/7741fb0f-db68-72aa-266f-c219d87a1b08.png)
引用元：[OpenLITのGitHubリポジトリ](https://github.com/openlit/openlit/blob/7640735810f76bfad7c8330e053e68d399ef6607/README.md)

いくつものモデルの情報を１つのダッシュボード上で監視することができるので、**複数のモデルを使用している方にとてもおすすめ**です！

:::note info
25種類のLLMモデルプロバイダーに対応
参考情報：[Monitor AI Applications using OpenTelemetry](https://docs.openlit.io/latest/integrations/introduction)
:::

### 特徴３：簡単にデプロイできる
わずか数ステップでLLMアプリケーションの監視ができるようになります。

詳細は本記事の３章および４章で説明します。


# ３. 前提環境の構築
まずはOpenLITを動作させるための環境を構築します。

## 利用サービス
- 開発環境：Amazon Elastic Compute Cloud（EC2）
- LLMモデルサービス：Amazon Bedrock

## AWSマネジメントコンソール上の準備
### Amazon Bedrock上でモデルの有効化
Amazon Bedrockのモデルを使用するために、モデルを有効化する必要があります。
過去に有効化を実施した場合、この手順は不要です。

AWSマネジメントコンソールから「Bedrock」を検索して、「Bedrock configurations」の「モデルアクセス」を選択します。
Bedrockでは、リージョンによって使用できるモデル数が大きく異なるためリージョンの選択が重要です。
今回は動作確認程度ですので、東京リージョン（`ap-northeast`）を選択します。

![region.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/230b4a89-4e63-b630-6e3b-26c9f4801a52.jpeg)

:::note warn
さらに多くのモデルを使用したい場合はバージニア北部（`us-east1`）もしくはオレゴン（`us-west2`）を選択しましょう。
:::

東京リージョンに変更できたら、「モデルアクセスを変更」を選択し、使用したいモデルを有効にしてください。
今回は``Claude 3 Haiku``を選択します。

![bedrock modelaccess.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/ab727fab-35a3-f00f-19ff-45ca04f59a49.jpeg)

:::note info
最新版である``Claude 3.5 Sonnet``を選択しない理由は、OpenLITの料金表にまだ反映されていないためです。
OpenLITの料金表については以下を参考にしてください。
参考情報：[Using the Default Pricing File](https://docs.openlit.io/latest/features/pricing#using-the-default-pricing-file)
:::


### EC2インスタンスの立ち上げ
AWSマネジメントコンソールから「EC2」を検索して、「インスタンスを起動」を選択します。

![ec2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/358c5172-add8-55fd-2a22-c349f95bcff5.jpeg)


**インスタンスの設定**
- 名前とタグ：任意（今回は`qiita-post`）
- AMI（OS）：Amazon Linux 2023
- インスタンスタイプ：任意（今回は`t3.medium`）
- キーペア：任意
- ネットワーク：セキュリティグループを作成（詳細は後述）
- ストレージ：任意（今回は16 GB）

:::note info
AMIに関して、他の候補でも問題ありませんが、この後のCLI上の操作に影響を与える可能性があります。
インスタンスタイプやストレージに関して、基本任意ですが、スペックが低すぎるとOpenLITが動作しない可能性があります。そのため、今回は「`t3.medium`」および「16 GB」としました。
:::

「インスタンスを起動」を選択すると作成完了です！

![ec2 instance.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/f1224787-2743-de89-e136-ab4e1fbe2a15.jpeg)

### セキュリティグループの設定
セキュリティグループは初期設定のままだと、すべての外部からのトラフィックを拒否しています。
OpenLITのダッシュボードは、EC2インスタンスのパブリックIPアドレスの3000番ポート上で動作します。そのため、セキュリティグループ設定で3000番ポートへのアクセスを許可する必要があります。

:::note info
`openlit`ディレクトリ内の`docker-coompose.yml`の設定を変更することでデフォルトの3000番ポートから、任意ポート番号に変更することが可能です。今回はデフォルトを使用しています。
:::

EC2の画面に戻り、先ほど作成したインスタンス（`qiita-post`）を選択します。
画面下部のセキュリティタブから「セキュリティグループ」を選択して、「インバウンドルールを編集」を選択します。

![security_groupe.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/0cb572f1-04ef-fd53-11db-2dd0654f924e.jpeg)

**インバウンドルールの設定**
- タイプ：カスタムTCP
- プロトコル：TCP
- ポート範囲：3000
- ソース：マイ IP（他のPCから受け付けたい場合は、範囲を広くする必要があります）
- 説明：任意

![inbaundo.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/9bd9fdd7-7d21-5f53-ad8b-2ef787870060.jpeg)

ルールを保存を選択して、完了です！

### EC2インスタンスにIAMロールをアタッチ
Bedrockの機能をEC2インスタンスで扱えるようにするため、``AmazoBedrockFullAccess``のポリシーが入ったIAMロールをアタッチする必要があります。

AWSマネジメントコンソールから「IAM」を検索して、「ロール」を選択、「ロールの作成」を選択します。

![IAM.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/7ffd83cd-195a-9e6a-07b5-a49db0460031.jpeg)


**IAMロールの設定**
- 信頼されたエンティティタイプ：AWSのサービス
- ユースケース：EC2
- 許可ポリシー：`AmazonBedrockFullAccess`
- ロールの詳細：任意（今回はロール名を`AmazonBedrockFullAccess`）

「ロールを作成」を選択すると作成完了です！

![BedrockFullAccess.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/e2e69419-80fc-439b-e59f-de7d934055c8.jpeg)

その後EC2に戻り、先ほど作成したインスタンスを選択します。
「アクション」の「セキュリティ」から「IAMロールを変更」を選択します。

![IAM role アタッチ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/976b2d87-8c83-336c-382b-01b0e73eeb6b.jpeg)

先ほど作成したIAMロール（`AmazonBedrockFullAccess`）を選択し、「IAMロールの更新」を選択すると完了です！

これで、EC2インスタンス上でBedrockを自由に扱うことができるようになりました！！
インスタンスの接続方法については、以下のページを参考にしてみてください。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html

https://qiita.com/clouda_AWS/items/ff03384e88c703edb7b4

https://qiita.com/hisato_imanishi/items/9993c86e02f5cbf4deae

インスタンスに接続できましたら、次はインスタンス上の準備です。


## EC2インスタンス上での準備
今回は``Amazon Linux 2023``の環境に前提となるツールやライブラリを導入していきます。
導入ツール・ライブラリは次の６つです。
- Docker
- Docker compose
- Python
- pip
- Boto3
- Git

「Docker」と「Docker compose」の導入に関しては、以下の記事を参考にさせていただきました。

https://zenn.dev/rock_penguin/articles/28875c7b0a5e30

### パッケージのアップデート
```:パッケージをアップデート
$ sudo dnf update
```

### Dockerのインストール
```:dockerインストールの手順
# dockerインストール
$ sudo dnf install -y docker

# dockerデーモン起動
$ sudo systemctl start docker

# ユーザーグループの追加
$ sudo gpasswd -a $(whoami) docker

# dockerに書き込み権限の付与
$ sudo chgrp docker /var/run/docker.sock

# dockerデーモンの再起動
$ sudo service docker restart

# dockerデーモンの自動起動
$ sudo systemctl enable docker
```

dockerのバージョンを確認して、正しくバージョンが確認できれば成功です！
```:dockerバージョン確認
$ docker -v
Docker version 25.0.5, build 5dc9bcc
```


### Docker composeのインストール
```:docker composeインストールの手順
# docker composeのインストール
$ sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 実行権限の付与
sudo chmod +x /usr/local/bin/docker-compose
```

docker-composeのバージョンを確認して、正しくバージョンが確認できれば成功です！
```:docker-composeバージョン確認
$ docker-compose -v
Docker Compose version v2.32.1
```



### Pythonとpipのインストール
```:pythonとpipをインストール
$ sudo dnf install python3 python3-pip -y
```

### AWSのライブラリ（Boto3）をインストール
```:boto3をインストール
$ pip install boto3
```

### Gitのインストール
```:gitをインストール
$ sudo yum install git -y
```

これで、OpenLITを導入する準備が全て整いました！！
長かった....。

# ４．OpenLITの導入
ついにOpenLITの導入に入ります。
以下のGitHubのページを参考に導入します。

https://github.com/openlit/openlit

## 導入手順
### OpenLITの導入
```:openlitインストールの手順
# openlitをクローン
$ git clone https://github.com/openlit/openlit.git

# openlitのライブラリをインストール
$ pip install openlit
```

以下のようにエラー文が表示される場合には、`distro`を適切なバージョンでインストールしましょう。

```:エラー文への対処
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
awscli 2.17.18 requires distro<1.9.0,>=1.5.0, but you have distro 1.9.0 which is incompatible.

# 対処法（distroをインストール）
$ pip install distro==1.8.0
```

### OpenLITの起動
```:OpenLIT起動手順
# ディレクトリを移動
$ cd openlit

# dockerコンテナを起動
$ sudo docker-compose up -d
```

これで、OpenLITの導入が完了し、生成AIを監視する準備がととのいました！
ツールの特徴にも示した通り、**OpenLIT自体の準備はとても簡単**でしたね！！

次は、生成AIを用いて自作したアプリケーションコードの情報をOpenLITに送ってみます。

# ５．OpenLITに接続
OpenLITにデータを送信するには以下のコードをPythonで書いた自作のアプリケーションコードに追記するだけです。

```python:openlitに送信
import openlit
openlit.init(otlp_endpoint="http://[EC2インスタンスのパブリックIPv4アドレス]:4318")
```


例えば、以下のようにBedrockのモデル（``claude-3-haiku``）を用いたアプリケーションコードにOpenLITのコードを書き加えてみます。
```python:bedrockのモデルを使用して、結果をopenlitに送信
# Python外部ライブラリをインポート
import boto3
import openlit

# OpenLITにデータを送信
openlit.init(otlp_endpoint="http://[EC2インスタンスのパブリックIPv4アドレス]:4318")

# Bedrock Runtimeクライアントを作成
bedrock_runtime = boto3.client(
    service_name = 'bedrock-runtime', 
    region_name = 'ap-northeast-1'
)
# 使用するモデルIDを設定
modelId = "anthropic.claude-3-haiku-20240307-v1:0"

# プロンプトを決定
prompt = "1日何時間睡眠をとるべきですか？"

# メッセージ作成
messages = [
    {
        "role": "user",
        "content": [{"text": prompt}],
    }
]

# 推論設定を構成
inferenceConfig = {
    "temperature": 0.1,
    "topP": 0.9,
    "maxTokens": 500,
    "stopSequences":[]
}

# Bedrock Runtimeで会話を実行
response = bedrock_runtime.converse(
    modelId=modelId ,
    messages=messages,
    inferenceConfig=inferenceConfig
)

# 応答結果を表示
print(response["output"]["message"]["content"][0]["text"])
```

:::note warn
エンドポイントにはご自身のEC2インスタンスのパブリックIPv4アドレスを設定してください。
:::

実行すると、以下のように応答結果が出力されました。
```:出力結果
一般的に、成人の適切な睡眠時間は以下のように言われています:

- 7~9時間が推奨されます。
- 6時間未満や10時間を超えるのは望ましくありません。
- 個人差がありますので、自分に合った睡眠時間を見つけることが大切です。

睡眠時間は年齢によっても異なります:

- 乳幼児: 12~17時間
- 学童期: 9~11時間
- 思春期: 8~10時間
- 高齢者: 7~8時間

睡眠の質も重要で、熟睡できることが大切です。
睡眠不足や睡眠の質が悪いと、集中力の低下や健康面での影響が出る可能性があります。
自分に合った適切な睡眠時間を見つけることをおすすめします。
```
（みなさんちゃんと8時間寝ていますか...？）
ここで、OpenLITにデータが送信されたか確認してみましょう！

``http://[インスタンスのパブリック IPv4 アドレス]:3000`` を確認すると、ログイン画面が表示されます。

![openlit login.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/82d71904-6e74-d2ae-0bfc-2b216db0aee5.jpeg)

EmailとPasswordを入力してログインします。
今回は初回なのでデフォルトの認証情報を使用しました。

- Email：`user@openlit.io`
- Password：`openlituser`

:::note warn
実際に運用する場合には、デフォルトを使い続けるのではなく、新しくユーザーを追加しましょう。
:::


すると、ダッシュボードが表示され、先ほどBedrockを使用したときのデータが送信されていることが確認できます！！

![openlit dashboard.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/289fd3f2-4e83-e288-2cbb-fab9639eaa37.jpeg)

コストやトークン数、使用したLLMのプロバイダーなどの情報がダッシュボード上で確認できていますね。

次に、Requestsページを確認してみます。

![openlit requests.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/77683742-ddce-6d3e-9218-ca984a8e565a.jpeg)

ここでは、各プロンプトとそれに対応するレスポンス内容、実行時刻、使用コストなどを確認することができます。

このように、OpneLITを用いてあなたの使用している**生成AIがちゃんと働いているか確認できる**ようになりました！！

# ６．苦労したところ
今回、OpenLITはもちろんのこと、AWSのサービスも初めて触りましたので、本当に多くの部分でつまずきました...。
（正直途中で諦めそうになりました。）

その中でも、特にみなさんにも関係のありそうな部分について紹介していきます。

## OpenLITが``invoke_model``関数への対応を終了していた
Bedrockのモデルを使用するにあたり、『Amazon Bedrock 生成AIアプリ開発入門』を参考にして進めていました。

https://www.google.co.jp/books/edition/Amazon_Bedrock_%E7%94%9F%E6%88%90AI%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA/vNEOEQAAQBAJ?hl=ja&gbpv=0

アプリケーションコードについて、初めはBedrockの``invoke_model``関数を用いてモデルを呼び出し、作成していました。
```python:invoke_modelを使用したモデルの呼び出し
# レスポンスを定義
response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
response_body = json.loads(response.get("body").read())
answer = response_body["content"][0]["text"]
```
そのソースファイルを実行すると、特にエラーもなく出力結果を受け取れるのですが、何度見てもOpenLITのダッシュボードには反映されていません。
そこで、「Wireshark」というツールを用いてパケットキャプチャを試みたところ、OpenLITへデータの送信が行われていないことがわかりました。

色々と探ってみると、どうやら``invoke_model``を使用していたことが問題のようでした。
OpenLITの2024年8月1日のマージ内容を確認してみると、**``invoke_model``への対応が終了しており、代わりに新しいモデルアクセス関数である``converse``を使用してください**とのことでした...。

> This PR fixes the issue found in #297 and also removes wrapping of invoke_model function in the Bedrock Instrumentation. Instead, The converse function will be wrapped.

https://github.com/openlit/openlit/pull/350

生成AI関連のツールや技術は、日々目まぐるしく進化して更新されてることがよくわかりました。そのため、**最新情報を常にチェックし続けることが重要**ですね！

:::note info
『Amazon Bedrock 生成AIアプリ開発入門』のGitHubリポジトリには、``converse``の実装後に更新されたソースコードが掲載されています。
参考情報：[bedrock-bookのGitHubリポジトリ](https://github.com/minorun365/bedrock-book/blob/main/chapter2/2-1_invoke-converse.py)
:::


## Database Configに誤りがあった
アプリケーションコードを実行した後にOpenLITのダッシュボードを開いたところ、データの受信に失敗しており、以下のようなエラー文が画面右下に表示されていました。

![username error.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884298/cbb36749-164c-ac33-00d4-b5bb785a3cb1.jpeg)

これはDBのユーザー名が誤っていることが原因でした。
openlitディレクトリ内の``docker-compose.yml``を確認すると、デフォルトのユーザー名とパスワードが記載されています。

```yml:docker-compose.yml
services:
  clickhouse:
    image: clickhouse/clickhouse-server:24.2.2
    container_name: clickhouse
    environment:
      CLICKHOUSE_PASSWORD: ${OPENLIT_DB_PASSWORD:-OPENLIT}
      CLICKHOUSE_USER: ${OPENLIT_DB_USER:-default}
    volumes:
      - clickhouse-data:/var/lib/clickhouse
    ports:
      - "9000:9000"
      - "8123:8123"
    restart: always

  openlit:
    image: ghcr.io/openlit/openlit:latest
    container_name: openlit
    environment:
      INIT_DB_HOST: clickhouse
      INIT_DB_PORT: 8123
      INIT_DB_DATABASE: ${OPENLIT_DB_NAME:-openlit}
      INIT_DB_USERNAME: ${OPENLIT_DB_USER:-default}
      INIT_DB_PASSWORD: ${OPENLIT_DB_PASSWORD:-OPENLIT}
      SQLITE_DATABASE_URL: file:/app/client/data/data.db
    ports:
      - "80:3000"
    depends_on:
      - clickhouse
    volumes:
      - openlit-data:/app/client/data
    restart: always
```


その情報をOpenLITのDBページに設定しなおすことで、問題なくLLMデータの受信ができるようになりました。

:::note warn
通常はデフォルトで正しいユーザー名が入力されているはずですが、私の場合はなぜか誤っていました。
:::

# ７．おわりに
今回はIT初学者が**生成AIに特化したObservabilityツールであるOpenLITを導入し、その概要についてまとめ**ました。

OpenLITの導入自体はとても簡単なコードなので、「なんだ簡単じゃん～」とか思っていましたが、思わぬところでとてつもなく苦労しました...。
ですが、みなさんこういう経験を経てエンジニアとして成長しておられると思いますので、私も１つくらいは階段を登れたのかなと信じています笑

**OpenLITは今回紹介したもの以外にも多くの機能を有しております**ので、みなさんもぜひ触ってみてください！
私も本記事とは別でOpenLITの具体的な機能に関する記事を投稿したいと考えています。

生成AIを用いたアプリケーションを作成して運用している方や、Observabilityについてこれから触っていこうと考えている方の参考になれば幸いです。

今後は、OpenLITの具体的な機能の調査やその他のObservabilityツールの紹介を投稿する予定です。

最後までお読みいただき、ありがとうございました。

---

2025/2/4 続編（OpenLITの詳細機能紹介）を執筆しました！

https://qiita.com/melhts/items/1bbfa659f9e43eae8a47

---