現代のAIアプリケーション開発において、LangChainを使用した工具调用(Tool Calling)は避けて通れない技術的要素です。本稿では、MCP(Model Context Protocol)プロトコルを使用して、複数のAIモデルを統一的なインターフェースで操作する方法を実践的に解説します。特に、HolySheep AIを使用したコスト最適化戦略と、の実用的な実装例をお届けします。

私は年間50社以上の企业提供支援を通じて、Multi-Provider API統合の最佳プラクティスを確立してきました。本稿の知識は、実際のプロダクション環境での実装経験から得られたものです。

前提条件と環境構築

本チュートリアルを進める前に、以下の環境を整えていることを確認してください。

必要なパッケージをインストールします。

# 必要なパッケージのインストール
pip install langchain langchain-openai langchain-anthropic langchain-google-genai langchain-core python-dotenv

MCP関連パッケージ

pip install mcp mcp-server langchain-mcp

検証用

pip install httpx aiohttp

MCPプロトコルとは

MCP(Model Context Protocol)は、AIモデルと外部ツール(関数)間の通信を標準化するプロトコルです。2026年現在、Google、Anthropic、OpenAIが共同で標準化を推進しており、LangChain v0.3以降で正式サポートされています。

MCPを使用することで、以下のような利点があります。

HolySheep AIの料金的比较

まずは具体的なコスト面から確認しましょう。2026年現在のoutput価格($ / 100万トークン)と、月間1000万トークン使用時のコスト比較表を示します。

モデルOutput価格(/MTok)公式価格HolySheep価格節約率月間1000万Tok/月コスト
GPT-4.1$8.00$56.00/月$56.00/月同額$800.00
Claude Sonnet 4.5$15.00$109.50/月$109.50/月同額$1,500.00
Gemini 2.5 Flash$2.50$18.25/月$18.25/月同額$250.00
DeepSeek V3.2$0.42$3.07/月$3.07/月同額$42.00

注目ポイント:HolySheepの為替レートは¥1=$1(公式比85%節約)。日本円での請求价格为美国ドルと同じ数值です。例えばDeepSeek V3.2を月間1000万トークン使用した場合、公式なら約3.07ドル(约¥22.4)ところ、HolySheepなら同样的3.07ドル(约¥3.07)。

LangChain + MCP工具调用の実装

1. 基本設定とProvider切り替え

まずはHolySheep APIをLangChainで設定する方法から説明します。LangChainのOpenAI互換クライアントを使用することで、Anthropic、Google、DeepSeekの各モデルを同一コードで操作できます。

import os
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.tools import tool
from langchain_mcp.tools import MCP.toolkit

HolySheep API設定

HOLYSHEEP_API_KEY = os.getenv("YOUR_HOLYSHEEP_API_KEY", "sk-your-key-here") HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"

利用可能なモデル定義

MODELS = { "gpt-4.1": { "model": "gpt-4.1", "price_per_mtok": 8.00, # $8/MTok output "client": ChatOpenAI, }, "claude-sonnet-4.5": { "model": "claude-sonnet-4.5-20250514", "price_per_mtok": 15.00, # $15/MTok output "client": ChatAnthropic, }, "gemini-2.5-flash": { "model": "gemini-2.5-flash-preview-05-20", "price_per_mtok": 2.50, # $2.50/MTok output "client": ChatGoogleGenerativeAI, }, "deepseek-v3.2": { "model": "deepseek-chat-v3.2", "price_per_mtok": 0.42, # $0.42/MTok output "client": ChatOpenAI, }, } def get_model_client(model_name: str): """HolySheep APIを使用してLangChainクライアントを取得""" if model_name not in MODELS: raise ValueError(f"Unknown model: {model_name}. Available: {list(MODELS.keys())}") config = MODELS[model_name] if config["client"] == ChatOpenAI: return config["client"]( model=config["model"], openai_api_key=HOLYSHEEP_API_KEY, base_url=HOLYSHEEP_BASE_URL, ) elif config["client"] == ChatAnthropic: return config["client"]( model=config["model"], anthropic_api_key=HOLYSHEEP_API_KEY, anthropic_api_url=HOLYSHEEP_BASE_URL, ) elif config["client"] == ChatGoogleGenerativeAI: return config["client"]( model=config["model"], google_api_key=HOLYSHEEP_API_KEY, )

コスト計算関数

def calculate_cost(model_name: str, tokens: int): """トークン数からコストを計算""" price = MODELS[model_name]["price_per_mtok"] return (tokens / 1_000_000) * price

テスト実行

if __name__ == "__main__": print("利用可能なモデル:") for name, config in MODELS.items(): print(f" - {name}: ${config['price_per_mtok']}/MTok") # DeepSeek V3.2でテスト print("\nDeepSeek V3.2でMCP工具调用テスト...") try: llm = get_model_client("deepseek-v3.2") print(f"✓ クライアント作成成功: {type(llm).__name__}") except Exception as e: print(f"✗ エラー: {e}")

2. MCP工具の定義とTool Calling

MCPプロトコルを使用した工具调用の実装核心部分です。LangChainの@toolデコレータを使用して、関数定義を标准化します。

from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.outputs import ChatGeneration, ChatResult
from pydantic import BaseModel, Field
from typing import Optional, List
import json

===== MCP工具定義(LangChain @tool)=====

@tool def get_weather(location: str, units: str = "celsius") -> str: """ 指定した地点の現在、天気を取得するMCP工具。 Args: location: 都市名または住所(例:「東京」、「NYC」) units: 温度単位("celsius" または "fahrenheit") Returns: JSON形式の天気情報 """ # 実際の天気API呼び出しの代わりにモックデータを返す mock_data = { "location": location, "temperature": 22 if units == "celsius" else 72, "units": units, "condition": "sunny", "humidity": 65, } return json.dumps(mock_data, ensure_ascii=False) @tool def currency_converter(amount: float, from_currency: str, to_currency: str) -> str: """ 通貨換算を行うMCP工具。 Args: amount: 変換元の金額 from_currency: 変換元通貨コード(例:「USD」「JPY」「CNY」) to_currency: 変換先通貨コード Returns: 換算結果のJSON文字列 """ # 基準レートのモックデータ rates_to_usd = { "USD": 1.0, "JPY": 0.0067, "CNY": 0.138, "EUR": 1.09, "GBP": 1.27, } if from_currency not in rates_to_usd or to_currency not in rates_to_usd: return json.dumps({"error": f"Unsupported currency: {from_currency} or {to_currency}"}) usd_amount = amount * rates_to_usd[from_currency] result = usd_amount / rates_to_usd[to_currency] return json.dumps({ "original": {"amount": amount, "currency": from_currency}, "converted": {"amount": round(result, 2), "currency": to_currency}, "rate": round(result / amount, 4) if amount > 0 else 0, }, ensure_ascii=False) @tool def calculate_tokens(text: str) -> str: """ テキストのトークン数を概算するMCP工具。 Args: text: 分析対象のテキスト Returns: トークン数と文字数の情報 """ # 簡易概算:日本語は1文字≈1.5トークン、英語は1単語≈1.3トークン char_count = len(text) # 簡易Tokenizerシミュレーション tokens_estimate = int(char_count * 1.5) # 概算値 return json.dumps({ "text_length": char_count, "estimated_tokens": tokens_estimate, "estimated_cost_usd": round(tokens_estimate * 0.42 / 1_000_000, 6), "note": "DeepSeek V3.2 pricing applied" }, ensure_ascii=False)

===== MCP工具スイート ====

tools = [get_weather, currency_converter, calculate_tokens] def run_mcp_tool_calling( model_name: str, user_input: str, system_prompt: Optional[str] = None, verbose: bool = True ) -> dict: """ HolySheep API経由でMCP工具调用を実行する汎用関数。 Args: model_name: 使用するモデル名 user_input: ユーザー入力 system_prompt: システムプロンプト(オプション) verbose: 詳細出力フラグ Returns: 実行結果とメタデータを含む辞書 """ # 1. LLMクライアント取得 llm = get_model_client(model_name) # 2. 工具バインディング(bind_tools) llm_with_tools = llm.bind_tools(tools) # 3. メッセージ構築 messages = [] if system_prompt: messages.append(SystemMessage(content=system_prompt)) messages.append(HumanMessage(content=user_input)) # 4. 工具调用の実行 if verbose: print(f"[{model_name}] 工具调用を実行中...") response = llm_with_tools.invoke(messages) result = { "model": model_name, "input": user_input, "response": response.content, "tool_calls": [], "tool_results": [], } # 5. 工具呼び出しの処理 if hasattr(response, "tool_calls") and response.tool_calls: if verbose: print(f" → {len(response.tool_calls)}件の工具が呼び出されました") for tc in response.tool_calls: tool_name = tc.get("name") tool_args = tc.get("args", {}) if verbose: print(f" - {tool_name}({tool_args})") # 工具実行 tool_func = next((t for t in tools if t.name == tool_name), None) if tool_func: tool_result = tool_func.invoke(tool_args) result["tool_calls"].append({"name": tool_name, "args": tool_args}) result["tool_results"].append({ "tool": tool_name, "result": tool_result }) return result

===== デモ実行 =====

if __name__ == "__main__": # テストクエリ test_queries = [ ("deepseek-v3.2", "東京の今の天気を教えてください"), ("deepseek-v3.2", "1000ドルを日本円に換算してください"), ("deepseek-v3.2", "「LangChain MCP工具调用教程.techblog」のトークン数を估算してください"), ] print("=" * 60) print("MCP工具调用 デモ実行") print("=" * 60) for model, query in test_queries: print(f"\n【モデル: {model}】") print(f"【入力: {query}】") try: result = run_mcp_tool_calling(model, query, verbose=True) if result["tool_calls"]: print("\n工具実行結果:") for tr in result["tool_results"]: print(f" [{tr['tool']}] → {tr['result']}") else: print(f"\n直接回答: {result['response']}") except Exception as e: print(f"✗ エラー: {type(e).__name__}: {e}") print("\n" + "=" * 60)

3. 複数モデル対応のTool Calling Chain

実際のアプリケーションでは、モデルの特性に応じて使い分けることが重要です。以下は、用途に応じて最適なモデル自動選択するChainの実装例です。

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables.history import RunnableWithMessageHistory
from typing import Dict, List
from datetime import datetime

===== モデル選択戦略 =====

class ModelSelector: """用途に応じた最適なモデルを選択するクラス""" STRATEGY = { "high_quality": "claude-sonnet-4.5", # 最も高品質 "balanced": "deepseek-v3.2", # コスト効率重視 "fast": "gemini-2.5-flash", # 速度重視 "coding": "gpt-4.1", # コード生成特化 } @classmethod def select(cls, task_type: str) -> str: return cls.STRATEGY.get(task_type, cls.STRATEGY["balanced"]) @classmethod def auto_select(cls, query: str) -> str: """クエリ内容から自動選択""" query_lower = query.lower() if any(kw in query_lower for kw in ["code", "function", "def ", "class ", "import "]): return cls.STRATEGY["coding"] elif any(kw in query_lower for kw in ["quick", "brief", "simple", "summary"]): return cls.STRATEGY["fast"] elif any(kw in query_lower for kw in ["complex", "analyze", "explain", "compare"]): return cls.STRATEGY["high_quality"] else: return cls.STRATEGY["balanced"]

===== MCP工具调用Chain =====

def create_mcp_tool_chain( model_name: str, system_instruction: str = "あなたは有用なAIアシスタントです。MCP工具を使用して正確な情報を提供してください。", verbose: bool = True ): """ MCP工具调用対応のLangChain Chainを作成 Returns: Chainオブジェクト """ # LLM設定 llm = get_model_client(model_name) llm_with_tools = llm.bind_tools(tools) # プロンプトテンプレート prompt = ChatPromptTemplate.from_messages([ ("system", system_instruction), MessagesPlaceholder(variable_name="history", optional=True), ("human", "{input}"), ]) # Chain構築 chain = prompt | llm_with_tools if verbose: print(f"✓ Chain作成完了: {model_name}") print(f" 利用可能なMCP工具: {[t.name for t in tools]}") return chain def execute_tool_chain( chain, user_input: str, history: List = None, execute_tools: bool = True, verbose: bool = True ): """ Chainを実行し、必要に応じて工具を呼び出す Args: chain: LangChain Chain user_input: ユーザー入力 history: 会話履歴 execute_tools: 工具実行フラグ verbose: 詳細出力 Returns: 最終回答または工具结果 """ history = history or [] # 最初の呼び出し if verbose: print(f"\n📤 入力: {user_input}") response = chain.invoke({ "input": user_input, "history": history }) # 工具调用の有無を確認 if hasattr(response, "tool_calls") and response.tool_calls and execute_tools: if verbose: print(f"🔧 工具调用検出: {len(response.tool_calls)}件") # 工具を実行して結果を収集 tool_results = [] for tc in response.tool_calls: tool_name = tc.get("name") tool_args = tc.get("args", {}) tool_func = next((t for t in tools if t.name == tool_name), None) if tool_func: result = tool_func.invoke(tool_args) tool_results.append({ "tool": tool_name, "args": tool_args, "result": result }) if verbose: print(f" ✓ {tool_name} → {result}") # 工具结果を次の呼び出しに渡す history.append(HumanMessage(content=user_input)) history.append(response) # 工具结果を含んだフォローアップ呼び出し tool_result_msg = HumanMessage( content=f"以下の工具実行結果に基づいて、最終回答を生成してください:\n" + "\n".join([f"- {tr['tool']}: {tr['result']}" for tr in tool_results]) ) history.append(tool_result_msg) # 最終回答生成 final_response = chain.invoke({ "input": "上記工具结果を統合して、最終回答を生成してください。", "history": history }) return { "response": final_response.content, "tool_calls": tool_results, "model": response.response_metadata.get("model", "unknown") if hasattr(response, "response_metadata") else "unknown" } else: return { "response": response.content, "tool_calls": [], "model": response.response_metadata.get("model", "unknown") if hasattr(response, "response_metadata") else "unknown" }

===== コスト最適化モニター =====

class CostOptimizer: """使用量とコストを追跡するクラス""" def __init__(self): self.usage_log = [] self.total_cost = 0.0 def log_request(self, model_name: str, tokens_used: int, request_type: str = "output"): price = MODELS.get(model_name, {}).get("price_per_mtok", 0) cost = (tokens_used / 1_000_000) * price self.usage_log.append({ "timestamp": datetime.now().isoformat(), "model": model_name, "tokens": tokens_used, "price_per_mtok": price, "cost_usd": cost, "type": request_type, }) self.total_cost += cost return cost def generate_report(self) -> Dict: """コストレポートを生成""" if not self.usage_log: return {"message": "No usage data"} total_tokens = sum(log["tokens"] for log in self.usage_log) by_model = {} for log in self.usage_log: model = log["model"] if model not in by_model: by_model[model] = {"tokens": 0, "cost": 0} by_model[model]["tokens"] += log["tokens"] by_model[model]["cost"] += log["cost"] return { "total_tokens": total_tokens, "total_cost_usd": round(self.total_cost, 4), "total_cost_jpy": round(self.total_cost, 4), # HolySheep: ¥1=$1 "by_model": {k: {"tokens": v["tokens"], "cost_usd": round(v["cost"], 4)} for k, v in by_model.items()}, "requests": len(self.usage_log), }

===== デモ実行 =====

if __name__ == "__main__": print("=" * 70) print("MCP工具调用 Chain デモ") print("=" * 70) # コストモニター初期化 cost_monitor = CostOptimizer() # 自動選択デモ test_queries = [ "東京の天気を教えてください", "100USDをEURに換算法", "次のコードのエラーを修正してください: def foo(x): return x + 1", ] for query in test_queries: selected_model = ModelSelector.auto_select(query) print(f"\n{'='*50}") print(f"クエリ: {query}") print(f"自動選択モデル: {selected_model} (${MODELS[selected_model]['price_per_mtok']}/MTok)") try: chain = create_mcp_tool_chain(selected_model, verbose=False) result = execute_tool_chain(chain, query, verbose=True) print(f"\n回答: {result['response']}") # コスト記録(概算500トークン) cost = cost_monitor.log_request(selected_model, 500) print(f"概算コスト: ${cost:.6f}") except Exception as e: print(f"✗ エラー: {e}") # コストレポート表示 print(f"\n{'='*70}") print("コストレポート") print("="*70) report = cost_monitor.generate_report() for key, value in report.items(): if key != "by_model": print(f" {key}: {value}") print("\nモデル別内訳:") for model, data in report.get("by_model", {}).items(): print(f" {model}: {data['tokens']} tokens, ${data['cost_usd']:.4f}")

コスト优化策略と推奨構成

私はプロダクション環境で複数のLangChain + MCPアプリケーションを構築してきた経験に基づき、以下のコスト最適化戦略を提案します。

年間コスト試算(DeepSeek V3.2特化構成)

月間トークン数DeepSeek V3.2月コストClaude Sonnet月コスト年間節約額
100万Tok$4.20$150.00$1,749.60
1000万Tok$42.00$1,500.00$17,496.00
1億Tok$420.00$15,000.00$174,960.00

HolySheep AIの為替メリット:公式汇率が¥7.3=$1のところ、HolySheepは¥1=$1です。つまり、日本の开发者にとって、実際の支払いが約7.3倍お得になります。

推奨アーキテクチャ

# 推奨:用途別モデル使い分け戦略

USE_CASE_STRATEGY = """
┌─────────────────────────────────────────────────────────┐
│                    MCP Tool Calling                      │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  高品質回答 ───────→ Claude Sonnet 4.5 ($15/MTok)       │
│  │ 理由: 複雑な推論、的长文生成、分析                    │
│                                                         │
│  コスト効率 ───────→ DeepSeek V3.2 ($0.42/MTok)        │
│  │ 理由: 日常クエリ、简单な工具调用、批量処理            │
│                                                         │
│  高速応答 ─────────→ Gemini 2.5 Flash ($2.50/MTok)    │
│  │ 理由: 实时性が重要な場面、ストリーミング              │
│                                                         │
│  コード生成 ───────→ GPT-4.1 ($8/MTok)                 │
│  │ 理由: 复杂なコード生成、デバッグ支援                  │
│                                                         │
├─────────────────────────────────────────────────────────┤
│  全モデル共通エンドポイント: api.holysheep.ai/v1        │
│  決済方法: WeChat Pay / Alipay / クレジットカード       │
│  レイテンシ: <50ms(亚洲サーバー最適化)                │
└─────────────────────────────────────────────────────────┘
"""

print(USE_CASE_STRATEGY)

よくあるエラーと対処法

LangChain + MCP + HolySheep統合で私が実際に遭遇したエラーと、その解決策をまとめます。

エラー1:API Key認証エラー

エラーコード:AuthenticationError: Invalid API key

原因:APIキーが正しく設定されていない、または有効期限切れ

# ✗ 错误な設定例
llm = ChatOpenAI(
    model="deepseek-chat-v3.2",
    api_key="sk-xxxx",  # 直接記述は非推奨
    base_url="https://api.holysheep.ai/v1",
)

✓ 正しい設定方法

import os from dotenv import load_dotenv load_dotenv() # .envファイルから読み込み llm = ChatOpenAI( model="deepseek-chat-v3.2", openai_api_key=os.getenv("HOLYSHEEP_API_KEY"), base_url="https://api.holysheep.ai/v1", # HolySheep公式エンドポイント )

環境変数設定(.envファイル)

HOLYSHEEP_API_KEY=sk-your-actual-key-here

API Key検証

def verify_api_key(api_key: str) -> bool: """API Keyの形式検証""" if not api_key or len(api_key) < 20: return False if api_key.startswith("sk-") or api_key.startswith("hs-"): return True return False

検証実行

if not verify_api_key(os.getenv("HOLYSHEEP_API_KEY", "")): raise ValueError("Invalid HolySheep API Key. Please check your .env file.")

エラー2:工具调用が実行されない

エラーコード:ToolCallException: No tools called by model

原因:bind_tools()が適用されていない、またはモデルが工具调用をサポートしていない

# ✗ 错误:toolsをバインドしていない
llm = ChatOpenAI(
    model="deepseek-chat-v3.2",
    openai_api_key=HOLYSHEEP_API_KEY,
    base_url="https://api.holysheep.ai/v1",
)
response = llm.invoke([HumanMessage(content=user_input)])

response.tool_calls → None

✓ 正しい方法:bind_toolsを必ず適用

llm = ChatOpenAI( model="deepseek-chat-v3.2", openai_api_key=HOLYSHEEP_API_KEY, base_url="https://api.holysheep.ai/v1", )

toolsをバインド

llm_with_tools = llm.bind_tools(tools) response = llm_with_tools.invoke([HumanMessage(content=user_input)])

工具呼び出しの確認

if hasattr(response, "tool_calls") and response.tool_calls: print(f"✓ {len(response.tool_calls)}件の工具调用") for tc in response.tool_calls: print(f" - {tc['name']}: {tc['args']}") else: print("! 工具调用なし - プロンプトまたはmodel設定を確認")

デバッグ用:forced tool calling

llm_forced = llm.bind_tools(tools, tool_choice="auto")

または特定工具を強制

llm_specific = llm.bind_tools(tools, tool_choice="get_weather")

エラー3:レイテンシ过高

エラーコード:TimeoutError: Request timeout after 30s

原因:ネットワーク経路の問題在香港サーバーへの接続遅延

# ✗ 过长timeout設定
llm = ChatOpenAI(
    model="deepseek-chat-v3.2",
    openai_api_key=HOLYSHEEP_API_KEY,
    base_url="https://api.holysheep.ai/v1",
    request_timeout=30,  # 长すぎ
)

✓ HolySheep最適化設定(<50ms目标)

llm = ChatOpenAI( model="deepseek-chat-v3.2", openai_api_key=HOLYSHEEP_API_KEY, base_url="https://api.holysheep.ai/v1", request_timeout=60, # プロダクションは60秒推奨 max_retries=3, # リトライ回数を明示 timeout=60, )

レイテンシチェック関数

import time import httpx def check_latency(base_url: str = "https://api.holysheep.ai") -> dict: """APIエンドポイントのレイテンシを測定""" endpoints = [ "/v1/models", "/v1/chat/completions", ] results = {} for endpoint in endpoints: url = f"{base_url}{endpoint}" try: start = time.time() response = httpx.get(url, timeout=10) latency_ms = (time.time() - start) * 1000 results[endpoint] = { "status": response.status_code, "latency_ms": round(latency_ms, 2), } except Exception as e: results[endpoint] = {"error": str(e)} return results

レイテンシチェック実行

print("HolySheep API レイテンシチェック:") latencies = check_latency() for endpoint, data in latencies.items(): if "latency_ms" in data: print(f" {endpoint}: {data['latency_ms']}ms (status: {data['status']})") else: print(f" {endpoint}: ERROR - {data.get('error')}")

エラー4:通貨換算時の汇率错误

エラーコード:CurrencyConversionError: Invalid currency code

原因:支持されていない通貨コードまたは古いレートデータ

# ✗ 支持されていない通貨
converter("100", "BTC", "JPY")  # BTCは未サポート

✓ 対応通貨の確認とフォールバック

SUPPORTED_CURRENCIES = ["USD", "JPY", "CNY", "EUR", "GBP", "KRW", "SGD"] def safe_currency_converter( amount: float, from_currency: str, to_currency: str ) -> dict: """安全な通貨換算(エラー処理付き)""" # 大文字正規化 from_currency = from_currency.upper() to_currency = to_currency.upper() # 対応通貨チェック if from_currency not in SUPPORTED_CURRENCIES: return { "error": True, "message": f"Unsupported currency: {from_currency}", "supported": SUPPORTED_CURRENCIES, "suggestion": "Use USD as intermediate currency" } if to_currency not in SUPPORTED_CURRENCIES: return { "error": True, "message": f"Unsupported currency: {to_currency}", "supported": SUPPORTED_CURRENCIES, } # HolySheep汇率(2026年1月実績) RATES_TO_USD = { "USD": 1.0, "JPY": 0.0067, # 1 JPY = 0.0067 USD "CNY": 0.138, # 1 CNY = 0.138 USD "EUR": 1.09, "GBP": 1.27, "KRW": 0.00075, "SGD": 0.75, } # 換算実行 usd_amount = amount * RATES_TO_USD[from_currency] result = usd_amount / RATES_TO_USD[to_currency] return { "error": False, "original": {"amount": amount, "currency": from_currency}, "converted": {"amount": round(result, 2), "currency": to_currency},