LiteLLM + LangChainでAzure OpenAI、AWS Bedrock(Anthropic Claude2)、GCP VertexAI(Palm2)へのマルチ問合せ

# LiteLLMとは
LiteLLMは複数のLLMの切替をシンプルに行うことができるライブラリ。Chat completionやembedding callなどに対応している。

https://litellm.ai/

今回、2023/9月末にプレビュ公開されたAWS Bedrockの疎通検証のため、Azure OpenAIリソースとの切替え方を検証した。（ついでGCP Palm2も。）

# インストール
LiteLLM自体の関連ライブラリインストールに加え、各LLMサービス(AOAI以外)利用に必要なライブラリをインストールする。

(LiteLLM)
!pip install google-generativeai
!pip install litellm

(Bedrock)
!pip install appdirs
!pip install boto3

(Palm2)
!pip install google-cloud-aiplatform

# 認証設定、利用設定 (Bedrock)
Bedrock(AWS)の認証情報は、AWS consoleにログイン後の右上自アカウントメニューからセキュリティ認証情報→IAMよりIAMアクセスキーを払い出して設定する。（AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/783eb269-ec54-c4fb-ab79-f2bef4e6d926.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/a5bb5ef3-b790-9c37-c36b-50fd41a13722.png)

また利用設定にはプレビューのため、申請が必要（だったはず。）利用可能リージョンも限られているので注意。
（ここらは公式最新情報を参照のこと。）
利用可能であれば、該当リージョンのAmazon Bedrockメニュー、Model accessより該当モデル（Claude）が利用可能になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/a860c986-742c-3af0-fb79-75e1bf3e415a.png)

※2023年9月28日に GA現在の利用可能リージョン（東京リージョンは非対応）
バージニア北部（ us-east-1 ）
オハイオ（ us-east-2 ）
オレゴン（ us-west-2 ）
シンガポール（ ap-southeast-1 ）


# 認証設定、利用設定 (Palm2)
GCP Palm2についてはGCPコンソールにログイン後、IAMと管理→サービスアカウントにて、サービスアカウントを作成し、APIキー（JSONタイプ）を作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/0323608b-8a9c-2123-3442-8a01d8316556.png)

GOOGLE_APPLICATION_CREDENTIALSにDLしたjsonファイルへのパスを設定。またVERTEXAI_PROJECTにプロジェクト名を設定する。

VertexAI model GardenにてPalm2 for Textにて詳細を確認することができる。（こちらも申請が必要だったかも。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/9f7587eb-79f6-740c-53f5-27d561fbe122.png)

# バージョン
Bedrockについて、かなり最新のバージョンが必要。
https://catalog.us-east-1.prod.workshops.aws/workshops/a4bdb007-5600-4368-81c5-ff5b4154f518/ja-JP/20-intro/21-environmentsetup
　→指定のVersion(boto3==1.26.140、botocore==1.29.140)だとboto3エラーが出たので、最新（boto3==1.28.58）とし、合わせて、botocoreも互換のあるバージョン(botocore==1.31.58)とした。LangChainも0.0.303。

```
pip install langchain==0.0.303
pip install boto3==1.28.58
pip install botocore==1.31.58
```

# 基本的な使い方(LiteLLM + LangChain)
```python
from langchain.chat_models import ChatLiteLLM
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    AIMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.schema import AIMessage, HumanMessage, SystemMessage

# AOAI gpt-35を使用する場合
chat = ChatLiteLLM(model="azure/gpt-35-turbo-16k")

messages = [
    HumanMessage(
        content="Translate this sentence from English to French. I love programming."
    )
]
res=chat(messages)

# Bedrock Claude2を使用する場合
chat2 = ChatLiteLLM(model="bedrock/anthropic.claude-v2")
res2=chat2(messages)
```
LangChainと組み合わせて使用する場合、ChatLiteLLMモデルを使用する。
このmodel指定にてAOAIのモデル、Bedrock、Palm2などのモデルを切り替えることができる。


# マルチLLM
以下あらためてLiteLLM + Langchainを使ってマルチLLMによる問合せを行うサンプルアプリを構築する。

LiteLLMのライブラリインポート
```python
# for LiteLLM
from langchain.chat_models import ChatLiteLLM
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    AIMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.schema import AIMessage, HumanMessage, SystemMessage
```

認証設定、モデル定義
```python
# AOAIの設定 
os.environ["AZURE_API_KEY"] = os.environ["OPENAI_API_KEY"] 
os.environ["AZURE_API_BASE"] = os.environ["OPENAI_API_HOST"]
os.environ["AZURE_API_VERSION"] = os.environ["OPENAI_API_VERSION"]

# AWS Bedrockの設定
os.environ["AWS_ACCESS_KEY_ID"] = ""
os.environ["AWS_SECRET_ACCESS_KEY"] = ""
os.environ["AWS_REGION_NAME"] = ""

# GCP Palm2の設定
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = ''
os.environ["VERTEXAI_PROJECT"] = "" 

# LLMモデル定義
Models = ["azure/gpt-35-turbo-16k", "azure/gpt-4", "bedrock/anthropic.claude-v2", "chat-bison-32k"]
```


streamlitによる入力フォームを作成。ModelはALL（すべてに回答させる）か、個別指定を選択できるようにしてみた。テキストボックスにチャットメッセージを入力し、入力ボタンで送信。

```python
LLMtype = st.selectbox("回答させるLLM", ["ALL"] + Models)

with st.form("my_form", clear_on_submit=True):
    text = st.text_area("入力")
    submitted = st.form_submit_button("入力")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/e2692e6e-f38c-bec0-4e80-babfa681c790.png)



各LLMからのメッセージ取得関数。chat-bison-32k（Palm2）の場合のみレスポンスメッセージがstr型でパースが必要だったため個別に処理。それ以外は.contentにて応答メッセージを取得できる。

```python
def getLLMMessage(LLMtype):
    llm=ChatLiteLLM(model=LLMtype)
    messages = [HumanMessage(content=text)]
    response=llm(messages)

    if LLMtype == "chat-bison-32k" :
        import re
        content_str = response.content
        matched = re.search(r"text='(.*?)',", content_str)
        if matched:
            extracted_text = matched.group(1)
            st.write(extracted_text)
    else:
        st.write(response.content)
```

ボタン押下後の実行部。ALLの場合は全てのLLMに対して問合せを行う。応答取得はランダムとなるので、取得順に画面に描写となる。
```python
if submitted:
    try:
        st.write(text)
        st.write("")
        with st.spinner("考え中..."):
            if LLMtype == "ALL" :            
                for LLMtype in Models :
                    getLLMMessage(LLMtype)
            else:
                getLLMMessage(LLMtype)                


    except Exception as e:
        response = str(e)
        if not response.startswith("Could not parse LLM output: `"):
            raise e
        response = response.removeprefix("Could not parse LLM output: `").removesuffix(
            "`"
        )
```

# 実行結果

質問「現在の日本の総理大臣は誰？」
に対する各LLMの回答。モデルの学習時点による知識の差がわかる。

- azure/gpt-35-turbo-16k
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/6053580d-4df4-ed48-eb08-371043b92803.png)
- azure/gpt-4
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/cb8d4c12-fdd8-e848-8d20-c4dc4d63b4c9.png)
- bedrock/anthropic.claude-v2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/92428c8b-342e-44fa-9a4d-faf233c1c3b9.png)
- chat-bison-32k
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/fa1bd895-b8c6-78bf-4017-f267e0513abf.png)


# 参考
https://docs.litellm.ai/docs/providers/azure

https://python.langchain.com/docs/integrations/chat/litellm