OpenRouterAPIでチャットアプリを作成してみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/814d49c1-3174-4bd5-a77c-62f2fb6e781e.png)

作成日：2025年3月23日(日)

## １．はじめに

最近、OpenRouterという一つのエンドポイントで様々なベンダーのLLM（大規模言語モデル）が利用できるサービスにかなり興味を持っています。

このOpenRouter APIの魅力は、一つのエンドポイントで「anthropic/claude-3.7-sonnet」や「google/gemini-2.0-flash-lite-001」などの複数の大規模言語モデルを同じプログラムで利用できる点です。

このたび、Roo Codeを使用してOpenRouter APIに接続するシンプルなCLI版チャットボットを作成しました。

このチャットボットは、Python初学者やチャットボット開発に興味のある方向けに作成した約100行程度の基本的なプログラムです。機能は最小限に抑えています。

![ChatExecutionExample.ja-JP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/dbd80657-0370-469a-86c9-1d696544ece9.png)

## ２．Roo Codeに与えるプロンプト

自律型AIエージェントのRoo Codeに次のプロンプトを与えました。私はPythonのプログラミングは基本的なレベルですが、今回は自力でコードを書く場合と、自律型AIエージェントを活用する場合とで、どの程度開発が効率化されるのかを検証したいと考えています。

なお、生成AIを利用しているため、このような簡潔なプロンプトでは結果に変動が生じる可能性があることをご了承ください。

```bash
OpenRouter APIを使用してテキストベースのチャットボットアプリケーションを作成してください。
OpenRouter APIのエンドポイント、モデル名は.envファイルから取得するようにしてください。
```

## ３．Roo Codeが生成してくれたコード

上記のプロンプトに基づいて、.envファイル、chat.pyファイル、requirements.txtファイルが生成されました。

シンプルながら良く出来ています。

```bash
OPENROUTER-CHAT-CLI/
│
├── .env
├── chat.py
└── requirements.txt

```

.envファイル

```bash
OPENROUTER_API_KEY=<YOUR_API_KEY>
MODEL_NAME=anthropic/claude-3.5-haiku
```

chat.pyファイル

```bash
import os
import requests
import json
from dotenv import load_dotenv

# Load environment variables from .env file (force reload)
load_dotenv(override=True)

# Get API key and model name from environment variables
api_key = os.getenv("OPENROUTER_API_KEY")
model_name = os.getenv("MODEL_NAME")

# Display debug information
print(f"Loaded environment variables:")
print(f"MODEL_NAME: {model_name}")

# Check if API key and model name are set
if not api_key:
    raise ValueError("OPENROUTER_API_KEY is not set in the .env file")
if not model_name:
    raise ValueError("MODEL_NAME is not set in the .env file")

# OpenRouter API endpoint
api_url = "https://openrouter.ai/api/v1/chat/completions"

# Set headers
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
    "HTTP-Referer": "https://localhost",  # OpenRouter requires this
    "X-Title": f"OpenRouter Chat with {model_name}"    # Optional: your app name
}

def chat_with_model(messages):
    """
    Function to chat with a model using the OpenRouter API
    
    Args:
        messages: Conversation history
        
    Returns:
        Response text from the model
    """
    payload = {
        "model": model_name,
        "messages": messages
    }
    
    try:
        response = requests.post(api_url, headers=headers, json=payload)
        response.raise_for_status()  # Raise an exception if there is an error
        
        response_data = response.json()
        assistant_message = response_data["choices"][0]["message"]["content"]
        return assistant_message
    
    except requests.exceptions.RequestException as e:
        print(f"API request error: {e}")
        if hasattr(e, 'response') and e.response:
            print(f"Response: {e.response.text}")
        return "An error occurred. Please try again."

def main():
    """
    Main conversation loop
    """
    print(f"Starting conversation with {model_name}. Type 'exit' to end.")
    print(f"Using model: {model_name}")
    
    # Conversation history
    messages = []
    
    while True:
        # Get user input
        user_input = input("\nYou: ")
        
        # Check exit command
        if user_input.lower() in ["exit", "quit", "end"]:
            print("Ending conversation.")
            break
        
        # Add user message to conversation history
        messages.append({"role": "user", "content": user_input})
        
        # Call API to get model response
        assistant_response = chat_with_model(messages)
        
        # Display assistant response
        print(f"\nAssistant: {assistant_response}")
        
        # Add assistant message to conversation history
        messages.append({"role": "assistant", "content": assistant_response})

if __name__ == "__main__":
    main()
```

※コメントやprint文内の日本語はRoo Codeに適切な英語に翻訳してもらっています。

requirements.txtファイル

```bash
requests==2.31.0
python-dotenv==1.0.0
```

より分かりやすくするために、Roo Codeが生成したコードに加えて、いくつかのファイルを追加してGitHubリポジトリを作成しました。

ただし、.gitignore以外のファイルはすべてRoo Codeに生成してもらい、imagesフォルダ内のSVGファイルはchat.pyをClaudeに送信して図示してもらったものなので、ほとんど修正を加えていません。

プロンプトをより詳細に記述するか、.clinerulesファイルを事前に用意しておけば、すべてを自動生成できる可能性がありますね。

```bash
OPENROUTER-CHAT-CLI/
│
├── .env
├── .env.example
├── .gitignore
├── chat.py
├── LICENSE.txt
├── README.ja-JP.md
├── README.md
├── requirements.txt
│
└── images/
    ├── ChatExecutionExample.ja-JP.png
    ├── ChatExecutionExample.png
    ├── openrouter-flow-diagram.ja-JP.svg
    └── openrouter-flow-diagram.svg
```

追加したファイル

| No | 追加したファイル | 説明 |
| --- | --- | --- |
| 1 | .env.example | OpenRouter APIキーを含む.envファイルを誤ってGitにコミットしないように、.env.exampleから.envを作成します。APIキーを設定後、.envは.gitignoreで除外します。 |
| 2 | .gitignore | Python仮想環境（venvフォルダ）や.envファイルをGitコミットから除外するための設定ファイルです。 |
| 3 | LICENSE.txt | 社内ルールに従い、OSSの使用には契約確認が必要なため、MIT Licenseを設定しています。 |
| 4 | README.ja-JP.md | プログラムの説明、機能、処理フロー、アーキテクチャ、システムコンポーネント、データフロー、セットアップ、使用方法、注意事項、ライセンスを記載しています（処理フローはClaudeのチャットでchat.pyから生成）。 |
| 5 | README.md | README.ja-JP.mdの内容をRoo Codeで英語に翻訳したものです。 |
| 6 | ChatExecutionExample.ja-JP.png | PowerShellでPython仮想環境を起動し、chat.pyに日本語で質問するデモの画面キャプチャです。 |
| 7 | ChatExecutionExample.png | ChatExecutionExample.ja-JP.pngと同様の操作を英語で実施した画面キャプチャです。 |
| 8 | openrouter-flow-diagram.ja-JP.svg | chat.pyの処理フローを、Claudeに「pythonプログラムの処理の流れを横長フォーマットでSVGで図示し、色分けの意味を凡例で示す」(*1)よう指示して生成したものです。 |
| 9 | openrouter-flow-diagram.svg | openrouter-flow-diagram.ja-JP.svgを英語に翻訳したバージョンです。 |

(*1) Claude.aiでchat.pyから生成した処理フロー図

![openrouter-flow-diagram.ja-JP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/fa3f8f27-c33c-4de9-be7c-8c57dfb4d715.png)

## ４．感想

Roo Codeにプロンプトを投入した朝7:10から、ファイルの追加とGitHubへのプッシュまで含めて8:20に完了しました。

わずか1時間10分で、初学者向けのOpenRouter APIを活用したサンプルチャットボットを構築できました。

以前は同じ作業に約15時間を要していたことを考えると、驚くべき進歩です。

2年前にPythonを熱心に学習しましたが、今回の開発ではPythonの知識をほとんど必要としませんでした。

初学者の方々は、このOpenRouterのサンプルプログラムを試していただくと良いでしょう。さらに、Roo Codeを使った開発にもぜひチャレンジしてみてください。

## ６．OpenRouterのクレジットの消費

今回の検証ではトータルで2.67USD(399円)のクレジットを消費しました。

![OpenRouterCreconsumptionCredits.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/022704c1-6de2-4934-bcf2-c03f908a074b.png)

内訳は以下の通りです。

| No | 用途 | 大規模言語モデル | 金額(USD) | 金額(日本円) |
| --- | --- | --- | --- | --- |
| 1 | Roo Codeでのプログラム開発 | anthropic/claude-3.7-sonnet | 2.66 | 397.2 |
| 2 | 生成したチャットボットのテスト | openai/o1-mini-2024-09-12 | 0.0114 | 1.7 |
| 3 | ↓ | google/gemini-2.0-flash-lite-001 | 0.00122 | 0.18 |
| 4 | ↓ | google/gemini-flash-1.5 | 0.000002 | 0.00030 |
|  | 合計 |  | 2.6714 | 398.91 |

※ドル円換算は１ドル＝148.62円で計算しています。

## ５．成果物

最終的な成果物をGitHubのpotofo/openrouter-chat-cliリポジトリにアップしてあります。

※2025年3月12日発表のWeb検索モデルも使えましたので、.env.exampleを更新してGitRepositoryにpushしておきました。（インターネット検索して答えてくれるモデルなのでかなり使いやすいです）
MODEL_NAME=openai/gpt-4o-search-preview
MODEL_NAME=openai/gpt-4o-mini-search-preview

https://github.com/potofo/openrouter-chat-cli

## ６．お勧め記事

https://qiita.com/potofo/items/d77c833224cc1493614f#51-openrouter