ChatGPTのAssistants APIを使ったわかったこと

# はじめに
先駆者さまがいろいろ記事を出してくれたおかげで、Assistants APIにつて理解が深まったので私もかるく使ってみました。
基本的には以下のTutorial通り利用しただけですが、使ってみるといろいろ気付けたことがあったので備忘録をここに残します。

https://platform.openai.com/docs/assistants/overview

# 気づいたこと
### ① Assistantは自然に消えない
Assistantは1回つくると永続？なんですかね。
作成後放置すると一定期間で消えてくれると思ってました。
このため何度もテストをしていたらすごい数のAssistantができちゃってました。
ちなみにAssistant作成状況は以下で確認できました。

```python
client = OpenAI()
""" 何個かAssistantを作成後 """
client.beta.assistants.list().__dict__

>> {'data': [Assistant(id='asst_ZFW***dw**yDk***OO**uC*E', created_at=1710231458, description=None, file_ids=[], instructions='You are a personal math tutor. Write and run code to answer math questions.', metadata={}, model='gpt-4-turbo-preview', name='Math Tutor', object='assistant', tools=[ToolCodeInterpreter(type='code_interpreter')])],.....}
```

無駄に作ってしまったAssistantは以下で削除できました。
```python
client.beta.assistants.delete('asst_ZFW***dw**yDk***OO**uC*E')

>> AssistantDeleted(id='asst_ZFW***dw**yDk***OO**uC*E', deleted=True, object='assistant.deleted')
```

### ② Assistantの管理がOrganaization単位
この件は[ココに](https://platform.openai.com/docs/assistants/how-it-works/data-access-guidance, "ChatGPT")記載がありましたが、
assistants, threads, messages, files の管理空間はorganaizationになるようです。
このためアプリ毎にAPI Tokenを使い分けていても、
AAAのトークンで作成したAssistantが、
BBBのトークンでインスタンス化したCliantから利用＆削除ができちゃいました。。

### ③ Threadsは一覧がみえない？
不要なThreadを削除するためにThread一覧がみたかったのですが、Treadsにはlistメソッドがない？のですかね。見つかりませんでした。
ただretrieveメソッドはあったので、都度Thread IDを管理しておけば削除等はできそうです。

```python
client.beta.threads.retrieve("thread_1z1j***4tMRG***OqSa***u1")

>> Thread(id='"thread_1z1j***4tMRG***OqSa***u1', created_at=1710231526, metadata={}, object='thread')
```

### ④ prompt_tokensが雪だるま式
これは[ココに](https://platform.openai.com/docs/assistants/how-it-works/managing-threads-and-messages, "ChatGPT")書いてあったので、認識はしていましたが、code_interpreterでデータ分析しているとすぐに数万トークンになりました。


### ⑤ 戻り値の平坦化
雑ですが、code_interpreterに関する戻り値は取得できました

```python
def ravel_json(input_data, key=None):
    def conv_dict(obj):
        try:
            return obj.__dict__
        except AttributeError:
            return obj

    input_data = conv_dict(input_data)
        
    dataDict = {}
    for current_key, val in input_data.items():
        if current_key.startswith('_'):
            continue

        full_key = f'{key}_{current_key}' if key else current_key

        if current_key == 'file_ids':
            dataDict[full_key] = ",".join(val)
            continue

        val = conv_dict(val)

        if isinstance(val, (dict, list)):
            if isinstance(val, dict):
                dataDict.update(ravel_json(val, full_key))
            else:  # val is a list
                if val:
                    for num, j in enumerate(reversed(val)):
                        j = conv_dict(j)
                        list_key = f'{full_key}_{num}'
                        if isinstance(j, dict):
                            dataDict.update(ravel_json(j, list_key))
                        else:
                            dataDict[list_key] = j
        else:
            dataDict[full_key] = val

    return dataDict


### 使い方 ###
client = OpenAI()
messages = client.beta.threads.messages.list(
            thread_id=thread_id,
            limit=7
            )
result = messages.data
raveledDatas = [ravel_json(val) for val in result]
```

### ⑥ 結構エラーがでて動きません（2024/03時点）
code_interpreterは以下のエラーがかなりでます。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2058950/bba10c94-cca5-49db-f8e4-0b85de1fd8e5.png)

また本記事の記載時点では、limitが9以上（デフォルト値は20）の場合、戻り値の中の‘file_ids’が消えてしまうようです。。 

```python
num=9  
client.beta.threads.messages.list(
            thread_id=self.thread_id,.
            limit=num
            )
```


徐々にアップデートしていきます