OCI Generative AI AgentsをGradioに実装してみた

# はじめに
OCI Generative AI Agents サービスはAIエージェントのマネージドサービスで、OCIのWebコンソール上でのチャット機能を標準で提供しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893065/aedaa17b-b05f-1b57-4bca-3f3ec05b4a50.png)
このようにOCIにログインしてWebコンソールから利用する方法以外に、APIで外部サービスからチャットを利用する方法について検証してみました。

Generative AI Agentsの基本的な機能については下記にまとめていただいています。

https://qiita.com/msasakaw/items/219c58ecdf98b4bfb743

OCI Python SDK を利用したGenerative AI Agents の操作については下記を参考にさせていただいております。

https://qiita.com/shukawam/items/c9eb9cd37950150d4d70


# 構成
本記事の内容は、OCI Generative AI Agentsのナレッジベースやチャットは設定できており、正常に動作している事を前提としています。
構成としては下記となりますが、本記事は主に左のComputeについてのお話となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893065/1a4929f3-5ec6-72e9-b9f3-51b9c321510e.png)




# 事前準備
今回はUbuntu 24.04 と Python 3.12を利用していますが、他の環境でも大きくは変わらないと考えています。
### OSの下準備
```bash:OSの下準備
# OSの最新化
sudo apt update
sudo apt upgrade -y

# venvのインストール
sudo apt install python3.12-venv -y

# アプリ用のvenvの作成
python3 -m venv ~/agents01
source ~/agents01/bin/activate
mkdir ./agents_app/
cd ./agents_app/

# 必要ライブラリのインストール
pip install gradio oci
```
### OCIのAPIの利用準備
OCIのAPIが利用できるように認証の設定を行います。
詳細は下記の記事などをご参考にしてください。

https://docs.oracle.com/ja-jp/iaas/Content/API/Concepts/sdk_authentication_methods.htm

今回は ```~/.oci/config``` にOCI接続の設定が記載されていて、正常にAPIが実行できる前提でのお話となります。

# Gradioのスクリプトを作成
### ライブラリのインポートと変数の定義
必要ライブラリと事前に定義できそうな変数を記載します
```python:app.py
import oci
import gradio as gr

# 作成したGenerative AI Agents のエンドポイントの OCID
agent_endpoint_id = "ocid1.genaiagentendpoint.oc1.us-chicago-1.XXXXXXXXXXXXXXXXXXXXXXXXXX"
# Generative AI Agents を実行するためのエンドポイントを明記（現在はシカゴにしか無いため）
service_endpoint = "https://agent-runtime.generativeai.us-chicago-1.oci.oraclecloud.com"
```

### Generative AI Agentsのクライアントの初期化
Generative AI Agentsとの通信を行うためのクライアントを定義して初期化します
```python:app.py
# クライアントの初期化
# 認証情報が ~/.oci/config に入ってる場合
config = oci.config.from_file("~/.oci/config")
agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(
    config=config,
    service_endpoint=service_endpoint
)
```

### チャットのセッションを作成する関数
セッション作成しないとチャットできないので、最初にセッションを作成する。
```python:app.py
def create_agent_session():
    response = agent_runtime_client.create_session(
        create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
            display_name="EXAMPLE-agent", # 任意のdisplay name
            description="EXAMPLE-description"), # 任意の説明
        agent_endpoint_id=agent_endpoint_id, # AgentのエンドポイントOCID
    )
    # response.data.id に session id が入っている
    return response.data.id
```
### チャットを実行する関数
ユーザー入力を受け取り、OCIのAPIと通信してAgentsに問合せ、帰ってきた結果を返す
```python:app.py
def get_agent_response(session,user_input):
    response = agent_runtime_client.chat(
        agent_endpoint_id = agent_endpoint_id,
        chat_details=oci.generative_ai_agent_runtime.models.ChatDetails(
            user_message=user_input,
            should_stream=False,
            session_id=session),
    )
    # response.data.message.content.text にAgentの答えが入っている
    return response.data.message.content.text
```

### Gradioの画面にチャットを表示する関数
Agentsから帰ってきた答えをGradioのチャット画面に表示する関数
```python:app.py
def chat_response(session, history, user_input):
    # 応答を生成する
    agent_response=get_agent_response(session, user_input)
    bot_response = f"回答: {agent_response}"
    history.append(("質問: " + user_input, bot_response))
    print (bot_response)
    return session, history, ""
```

### Gradioのインターフェース作成
Gradioで簡易UIを作成
```python:app.py
with gr.Blocks() as chat_interface:
    # タイトル
    gr.Markdown("## OCIの疑問にお答えbot")
    
    # チャット履歴用のコンポーネント
    chat_history = gr.Chatbot()
    
    # 入力ボックスと送信ボタン
    user_input = gr.Textbox(label="OCIに関する疑問を入力してください", placeholder="ここに質問を入力", lines=1)
    send_button = gr.Button("Send")
    
    #Agentのsession初期化
    session_id=create_agent_session()
    
    # 状態管理
    session = gr.State(session_id) #セッションIDをここに保持
    history_state = gr.State([]) #チャット履歴をここに保持
    
    # ユーザー入力時の動作
    send_button.click(
        chat_response,
        inputs=[session, history_state, user_input], 
        outputs=[session, chat_history, user_input]
    )

# 実行
chat_interface.launch(
    server_name="0.0.0.0"
)
```
# アプリ実行
```bash
# OCIはデフォルトでファイアーウォール有効なので、必要に応じて通信の許可
# また、OCIのセキュリティリストで TCP 7860 のイングレスが許可されていること
sudo iptables -F
# Gradio UI の実行
python3 app.py
```
インスタンスのパブリックIP:7860 にアクセスするとチャット画面が表示されます。
Agentsと同様の受け答えが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893065/51842838-afd3-c38f-b792-798d0b931ce0.png)

# まとめ
以上が外部アプリからの Generative AI Agentsの利用方法の例となります。
Gradio以外でも大まかに同様の方法でチャット機能を実装できますので、参考になれば幸いです。