<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Llama on AI2CORE - AI技術ブログ</title>
    <link>https://www.ai2core.com/tags/llama/</link>
    <description>Recent content in Llama on AI2CORE - AI技術ブログ</description>
    <generator>Hugo -- 0.146.4</generator>
    <language>ja</language>
    <lastBuildDate>Sat, 21 Feb 2026 12:00:00 +0900</lastBuildDate>
    <atom:link href="https://www.ai2core.com/tags/llama/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Cloudflare Workers AIでエッジ推論を実践する</title>
      <link>https://www.ai2core.com/posts/2026-02-21-cloudflare-workers-ai/</link>
      <pubDate>Sat, 21 Feb 2026 12:00:00 +0900</pubDate>
      <guid>https://www.ai2core.com/posts/2026-02-21-cloudflare-workers-ai/</guid>
      <description>Workers AIを使ってLlama 3をエッジで動かすチュートリアル。</description>
      <content:encoded><![CDATA[<h1 id="cloudflare-workers-aiでエッジ推論を実践するllama-3をサーバーレスで動かすサーバーレスaiの最前線">Cloudflare Workers AIでエッジ推論を実践する：Llama 3をサーバーレスで動かすサーバーレスAIの最前線</h1>
<h2 id="はじめに">はじめに</h2>
<p>「自社のアプリケーションに最新のLLM（大規模言語モデル）を組み込みたいが、高価なGPUサーバーの運用コストや複雑なインフラ管理が壁になっている…」
「AIチャットボットを作ったはいいものの、APIのレスポンスが遅くてユーザー体験が悪い…」
「そもそも、AI推論環境をどう構築すればいいのか、最初の一歩が踏み出せない…」</p>
<p>多くのエンジニアが、AI、特にLLMをプロダクトに導入する際に、このような課題に直面しているのではないでしょうか。AIの力は魅力的ですが、その裏にはコスト、パフォーマンス、そして運用の複雑さという大きなハードルが存在します。</p>
<p>もし、これらの課題を解決し、<strong>サーバーの管理を一切行わずに、世界中のユーザーから最も近い場所で、低遅延かつ低コストでLlama 3のような高性能LLMを動かせる</strong>としたらどうでしょう？</p>
<p>この記事では、それを実現するCloudflareの画期的なサービス「Workers AI」について、その核心から実践的な使い方までを徹底的に解説します。この記事を読み終える頃には、あなたはWorkers AIの基本をマスターし、実際にLlama 3をエッジで動かすサーバーレスAIアプリケーションを自分の手で構築できるようになっているはずです。さあ、サーバーレスAIの最前線へ、一緒に飛び込んでいきましょう。</p>
<h2 id="なぜ今エッジでのai推論が重要なのか">なぜ今、エッジでのAI推論が重要なのか？</h2>
<p>ChatGPTの登場以来、LLMは技術の世界に革命をもたらしました。しかし、その強力な能力を広くアプリケーションに組み込むには、いくつかの根深い課題が存在します。</p>
<h3 id="従来のai推論が抱える課題">従来のAI推論が抱える課題</h3>
<ol>
<li><strong>高コスト</strong>: 高性能なAIモデル、特にLLMの推論には、強力なGPUが必要です。これらのGPUサーバーを購入またはレンタルするには莫大な費用がかかり、特にスモールスタートしたいプロジェクトにとっては大きな障壁となります。</li>
<li><strong>高レイテンシ</strong>: 従来のAI推論は、特定のリージョンに存在する大規模なデータセンターで実行されるのが一般的でした。ユーザーがデータセンターから物理的に遠い場所にいる場合、ネットワークの往復時間（RTT）がボトルネックとなり、応答が遅れてしまいます。リアルタイム性が求められるチャットボットやインタラクティブなアプリケーションでは、この遅延は致命的です。</li>
<li><strong>複雑なインフラ管理</strong>: GPUサーバーのプロビジョニング、OSやライブラリのバージョン管理、セキュリティパッチの適用、そしてトラフィックに応じたスケーリング… AIモデルを安定して稼働させるためには、専門的な知識を持つインフラエンジニアによる24時間365日の運用が不可欠でした。</li>
<li><strong>スケーラビリティの難しさ</strong>: バイラルヒットしたサービスのように、アクセスが急増した際、迅速にインフラをスケールさせるのは容易ではありません。需要を予測して事前にサーバーを準備しておく必要があり、コストの最適化も困難でした。</li>
</ol>
<p>これらの課題は、多くの開発者がAI活用のアイデアを形にするのをためらわせる原因となっていました。</p>
<h3 id="解決策としてのサーバーレスaiとエッジコンピューティング">解決策としての「サーバーレスAI」と「エッジコンピューティング」</h3>
<p>こうした状況を打破するために登場したのが、「サーバーレスAI」という新しいパラダイムです。これは、Cloudflare Workers AIが提唱するコンセプトで、その名の通り、開発者がサーバーインフラを一切意識することなくAIモデルを利用できる仕組みです。</p>
<p>この中核をなすのが<strong>エッジコンピューティング</strong>です。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>【従来の集中型モデル】
</span></span><span style="display:flex;"><span>  [ユーザー] &lt;---- (高いレイテンシ) ----&gt; [中央データセンター (GPUサーバー)]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>【エッジコンピューティングモデル】
</span></span><span style="display:flex;"><span>  [ユーザー] &lt;--&gt; (低いレイテンシ) &lt;--&gt; [最寄りのCloudflareエッジ拠点]
</span></span><span style="display:flex;"><span>                                             |
</span></span><span style="display:flex;"><span>                                        [Workers AIで推論実行]
</span></span></code></pre></td></tr></table>
</div>
</div><p>エッジコンピューティングは、計算処理をユーザーの物理的な位置の近く（＝エッジ）で行う技術です。Cloudflareは世界120カ国以上、300都市以上に広がる広大なグローバルネットワークを持っており、Workers AIはこのネットワーク上の無数のサーバーでAIモデルの推論を実行します。</p>
<p>これにより、ユーザーからのリクエストは最も近いエッジ拠点で処理されるため、<strong>物理的な距離に起因するレイテンシを劇的に削減</strong>できます。さらに、インフラはCloudflareが完全に管理してくれるため、開発者はコードを書くことだけに集中できます。コストも実際に推論を実行した分だけの従量課金制であり、スケーラビリティもCloudflareのネットワークが自動で担保してくれます。</p>
<p>Cloudflare Workers AIは、まさに従来のAI推論が抱えていたコスト、レイテンシ、運用の課題をまとめて解決する、ゲームチェンジャー的な存在なのです。</p>
<h2 id="workers-aiでllama-3を動かすハンズオンチュートリアル">Workers AIでLlama 3を動かす！ハンズオンチュートリアル</h2>
<p>それでは、実際にCloudflare Workers AIを使って、Meta社が開発した最新のオープンソースLLM「Llama 3」を動かすアプリケーションを構築していきましょう。驚くほど簡単であることに、きっと驚かれるはずです。</p>
<h3 id="ステップ1-環境構築">ステップ1: 環境構築</h3>
<p>まず、開発に必要なツールをセットアップします。必要なのはNode.jsと、Cloudflare Workersを管理するためのCLIツール <code>wrangler</code> です。</p>
<ol>
<li>
<p><strong>Node.jsとnpmのインストール</strong>:
もしまだインストールしていなければ、公式サイトからご自身の環境に合ったものをインストールしてください。</p>
</li>
<li>
<p><strong>Wrangler CLIのインストール</strong>:
ターミナルを開き、以下のコマンドを実行して <code>wrangler</code> をグローバルにインストールします。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npm install -g wrangler
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Cloudflareアカウントへのログイン</strong>:
<code>wrangler</code> があなたのCloudflareアカウントを操作できるように、認証を行います。以下のコマンドを実行するとブラウザが開き、ログインを求められます。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wrangler login
</span></span></code></pre></td></tr></table>
</div>
</div><p>ログインが成功すれば、準備は完了です。</p>
</li>
</ol>
<h3 id="ステップ2-workersプロジェクトの作成">ステップ2: Workersプロジェクトの作成</h3>
<p>次に、<code>wrangler</code> を使ってWorkers AI用のプロジェクトテンプレートから新しいプロジェクトを作成します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npm create cloudflare@latest my-llama-worker -- --template<span style="color:#f92672">=</span>worker-ai
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>my-llama-worker</code> という名前のディレクトリが作成され、中にいくつかのファイルが生成されます。主なファイルは以下の通りです。</p>
<ul>
<li><code>wrangler.toml</code>: プロジェクトの設定ファイル。Workerの名前やAIモデルのバインディングなどを定義します。</li>
<li><code>src/index.ts</code>: Workerの本体となるTypeScriptのソースコードです。ここにロジックを記述します。</li>
</ul>
<h3 id="ステップ3-aiバインディングの設定">ステップ3: AIバインディングの設定</h3>
<p>WorkerからWorkers AIの機能を利用するには、<code>wrangler.toml</code> ファイルで「AIバインディング」を設定する必要があります。これにより、コード内から <code>AI</code> という名前でWorkers AIの機能にアクセスできるようになります。</p>
<p><code>wrangler.toml</code> を開き、以下の内容を追加または確認してください。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#75715e"># wrangler.toml</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;my-llama-worker&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span> = <span style="color:#e6db74">&#34;src/index.ts&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">compatibility_date</span> = <span style="color:#e6db74">&#34;2024-04-05&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Workers AIへのアクセスを有効にするためのバインディング</span>
</span></span><span style="display:flex;"><span>[[<span style="color:#a6e22e">ai</span>]]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">binding</span> = <span style="color:#e6db74">&#34;AI&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>この <code>[[ai]]</code> ブロックが、<code>env.AI</code> という形でコードからAI機能を使えるようにするための魔法の呪文です。</p>
<h3 id="ステップ4-llama-3を呼び出すコードの実装">ステップ4: Llama 3を呼び出すコードの実装</h3>
<p>いよいよ核心部分である、Llama 3を呼び出すコードを書いていきましょう。<code>src/index.ts</code> を開き、以下のように編集します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#75715e">// src/index.ts
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 環境変数（AIバインディングを含む）の型定義
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Env</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">AI</span>: <span style="color:#66d9ef">Ai</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">default</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// fetchイベントハンドラ：Workerがリクエストを受け取ったときに実行される
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>: <span style="color:#66d9ef">Request</span>, <span style="color:#a6e22e">env</span>: <span style="color:#66d9ef">Env</span>, <span style="color:#a6e22e">ctx</span>: <span style="color:#66d9ef">ExecutionContext</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">Response</span>&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// URLのクエリパラメータから &#39;prompt&#39; を取得
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> { <span style="color:#a6e22e">searchParams</span> } <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">prompt</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">searchParams</span>.<span style="color:#66d9ef">get</span>(<span style="color:#e6db74">&#39;prompt&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// プロンプトが指定されていない場合はエラーメッセージを返す
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">prompt</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#e6db74">&#39;Error: &#34;prompt&#34; query parameter is required.&#39;</span>, { <span style="color:#a6e22e">status</span>: <span style="color:#66d9ef">400</span> });
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// env.AI.run() を使ってLlama 3モデルを呼び出す
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 第1引数: 実行したいモデルのID
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 第2引数: モデルへの入力データ
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;@cf/meta/llama-3-8b-instruct&#39;</span>,
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">prompt</span>: <span style="color:#66d9ef">prompt</span>,
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// AIからの応答をJSON形式でクライアントに返す
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">response</span>), {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span> },
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></td></tr></table>
</div>
</div><p>コードのポイントを解説します。</p>
<ul>
<li><strong><code>export interface Env</code></strong>: <code>wrangler.toml</code> で設定した <code>AI</code> バインディングをTypeScriptの型システムに認識させるための定義です。</li>
<li><strong><code>async fetch(request: Request, env: Env, ...)</code></strong>: これがWorkerのエントリーポイントです。<code>env</code> オブジェクトを通じて <code>AI</code> バインディングにアクセスできます。</li>
<li><strong><code>const prompt = searchParams.get('prompt')</code></strong>: URLのクエリパラメータ（例: <code>?prompt=こんにちは</code>）からプロンプト文字列を取得しています。</li>
<li><strong><code>await env.AI.run(...)</code></strong>: ここがWorkers AIを呼び出している部分です。
<ul>
<li><code>'@cf/meta/llama-3-8b-instruct'</code>: Cloudflareが提供するLlama 3 8B InstructモデルのIDです。他にも様々なモデルが利用可能です。</li>
<li><code>{ prompt: prompt }</code>: モデルへの入力です。最もシンプルな形式でプロンプトを渡しています。</li>
</ul>
</li>
<li><strong><code>new Response(...)</code></strong>: モデルからの推論結果（<code>response</code>）をJSON形式に変換して、HTTPレスポンスとして返却しています。</li>
</ul>
<p>たったこれだけのコードで、Llama 3を呼び出すAPIが完成しました。</p>
<h3 id="ステップ5-ローカルでのテスト">ステップ5: ローカルでのテスト</h3>
<p>デプロイする前に、ローカル環境で動作を確認しましょう。ターミナルで以下のコマンドを実行します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wrangler dev
</span></span></code></pre></td></tr></table>
</div>
</div><p>これにより、ローカル開発サーバーが起動します。<code>http://localhost:8787</code> でリクエストを受け付ける状態になります。</p>
<p>別のターミナルを開き、<code>curl</code> コマンドを使ってAPIを叩いてみましょう。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># プロンプトをURLエンコードして渡す</span>
</span></span><span style="display:flex;"><span>curl <span style="color:#e6db74">&#34;http://localhost:8787/?prompt=Cloudflare%20Workers%20AI%E3%81%AE%E9%AD%85%E5%8A%9B%E3%82%923%E3%81%A4%E6%95%99%E3%81%88%E3%81%A6&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>しばらく待つと、以下のようなJSON形式のレスポンスが返ってくるはずです。（内容は実行ごとに異なります）</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;response&#34;</span>: <span style="color:#e6db74">&#34;もちろんです！Cloudflare Workers AIの魅力を3つご紹介します。\n\n1.  **超低レイテンシ**: 世界中に分散したCloudflareのエッジネットワーク上で推論が実行されるため、ユーザーに最も近い場所で処理が行われます。これにより、従来のクラウドAIサービスと比較して劇的に高速な応答が可能です。\n\n2.  **サーバーレスで簡単**: 開発者はインフラの管理やスケーリングについて一切心配する必要がありません。Wrangler CLIを使って数コマンドでデプロイでき、コードを書くことに集中できます。\n\n3.  **驚異的なコストパフォーマンス**: GPUサーバーを常時稼働させる必要がなく、実際に推論を実行した分だけの従量課金制です。 generousな無料枠も用意されており、個人開発やプロトタイピングにも最適です。&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></td></tr></table>
</div>
</div><p>見事にLlama 3がローカル環境で動作しました！</p>
<h3 id="ステップ6-cloudflareへデプロイ">ステップ6: Cloudflareへデプロイ</h3>
<p>最後に、作成したWorkerをCloudflareのグローバルネットワークにデプロイします。コマンドはたった一つです。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wrangler deploy
</span></span></code></pre></td></tr></table>
</div>
</div><p>コマンドが成功すると、あなたのWorkerに割り当てられた公開URL（例: <code>https://my-llama-worker.YOUR_SUBDOMAIN.workers.dev</code>）が表示されます。</p>
<p>今度はこの公開URLに対して、先ほどと同じように<code>curl</code>でリクエストを送ってみましょう。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl <span style="color:#e6db74">&#34;https://my-llama-worker.YOUR_SUBDOMAIN.workers.dev/?prompt=Cloudflare%20Workers%20AI%E3%81%AE%E9%AD%85%E5%8A%9B%E3%82%923%E3%81%A4%E6%95%99%E3%81%88%E3%81%A6&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>世界中のどこからアクセスしても、あなたの現在地から最も近いエッジ拠点でLlama 3が実行され、驚くほど高速に応答が返ってくることを体感できるはずです。</p>
<h2 id="メリットとデメリットそして他ツールとの比較">メリットとデメリット、そして他ツールとの比較</h2>
<p>Workers AIは非常に強力ですが、万能ではありません。その特性を理解し、他の選択肢と比較することで、最適な技術選定が可能になります。</p>
<h3 id="workers-aiのメリット">Workers AIのメリット</h3>
<ul>
<li><strong>圧倒的な低レイテンシ</strong>: ユーザーの近くで実行されるため、物理的な遅延が最小限に抑えられます。</li>
<li><strong>驚異的な低コスト</strong>: 従量課金制で、無料枠も充実しています。高価なGPUサーバーを維持する必要がありません。</li>
<li><strong>究極のシンプルさ</strong>: サーバーレスなのでインフラ管理は不要。<code>wrangler deploy</code> だけでグローバルに展開できます。</li>
<li><strong>自動スケーリング</strong>: Cloudflareの巨大なネットワークが、アクセスの増減に合わせて自動でスケールしてくれます。</li>
<li><strong>豊富なモデルラインナップ</strong>: テキスト生成（Llama 3, Gemma, Mistralなど）、画像生成（Stable Diffusion）、埋め込み、音声認識など、多様なタスクに対応したモデルがプリセットされています。</li>
</ul>
<h3 id="workers-aiのデメリットと注意点">Workers AIのデメリットと注意点</h3>
<ul>
<li><strong>モデルの制約</strong>: Cloudflareが提供する最適化されたモデルしか利用できません。自前で学習させたカスタムモデルを持ち込むことは（現時点では）できません。</li>
<li><strong>限定的なカスタマイズ</strong>: モデルのFine-tuning（微調整）のような高度なカスタマイズはサポートされていません。</li>
<li><strong>プラットフォームの実行制限</strong>: Workersプラットフォーム自体の実行時間やメモリの制限を受けます。非常に長時間の推論や大規模なデータ処理には向かない場合があります。</li>
<li><strong>ベンダーロックイン</strong>: Cloudflareのエコシステムに依存する形になるため、将来的に他のプラットフォームへ移行する際の障壁になる可能性があります。</li>
</ul>
<h3 id="他のai推論プラットフォームとの比較">他のAI推論プラットフォームとの比較</h3>
<table>
  <thead>
      <tr>
          <th style="text-align: left">特徴</th>
          <th style="text-align: left">Cloudflare Workers AI</th>
          <th style="text-align: left">AWS SageMaker / Google Vertex AI</th>
          <th style="text-align: left">Hugging Face Inference Endpoints</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: left"><strong>パラダイム</strong></td>
          <td style="text-align: left">サーバーレス, エッジ</td>
          <td style="text-align: left">フルマネージド, 集中型クラウド</td>
          <td style="text-align: left">マネージドインスタンス, 集中型クラウド</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>レイテンシ</strong></td>
          <td style="text-align: left"><strong>非常に低い</strong></td>
          <td style="text-align: left">高い（エッジ構成は複雑）</td>
          <td style="text-align: left">高い</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>コスト</strong></td>
          <td style="text-align: left"><strong>非常に低い（従量課金）</strong></td>
          <td style="text-align: left">高い（インスタンス時間課金）</td>
          <td style="text-align: left">比較的高い（インスタンス時間課金）</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>運用</strong></td>
          <td style="text-align: left"><strong>非常に簡単</strong></td>
          <td style="text-align: left">複雑（多くの設定項目）</td>
          <td style="text-align: left">比較的簡単</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>スケーリング</strong></td>
          <td style="text-align: left">自動（非常に得意）</td>
          <td style="text-align: left">自動（設定が必要）</td>
          <td style="text-align: left">自動（設定が必要）</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>モデルの自由度</strong></td>
          <td style="text-align: left">低い（提供モデルのみ）</td>
          <td style="text-align: left"><strong>非常に高い（カスタムモデル可）</strong></td>
          <td style="text-align: left"><strong>非常に高い（HF Hubの全モデル）</strong></td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>Fine-tuning</strong></td>
          <td style="text-align: left">不可</td>
          <td style="text-align: left"><strong>可能</strong></td>
          <td style="text-align: left">可能</td>
      </tr>
      <tr>
          <td style="text-align: left"><strong>得意な用途</strong></td>
          <td style="text-align: left">低レイテンシなAPI, チャットボット, プロトタイプ</td>
          <td style="text-align: left">研究開発, 高度なカスタムモデル, 大規模バッチ処理</td>
          <td style="text-align: left">豊富なモデルの活用, 研究開発</td>
      </tr>
  </tbody>
</table>
<p><strong>結論として、Workers AIは「ユーザー向けのインタラクティブなAI機能を、低コスト・低レイテンシで素早く提供したい」というユースケースにおいて、現時点で最強の選択肢の一つと言えるでしょう。</strong> 一方で、独自のモデルを動かしたい、あるいは複雑なFine-tuningが必要な場合は、AWS SageMakerやVertex AIのような、より自由度の高いプラットフォームを検討する必要があります。</p>
<h2 id="現場で使える実践的なtips">現場で使える実践的なTips</h2>
<p>基本的な使い方をマスターしたところで、さらに実践的なアプリケーションを構築するためのTipsをいくつかご紹介します。</p>
<h3 id="1-ストリーミングでuxを向上させる">1. ストリーミングでUXを向上させる</h3>
<p>LLMの応答は生成に時間がかかるため、全てのテキストが生成されるのを待っているとユーザーは待たされてしまいます。これを解決するのが<strong>ストリーミング応答</strong>です。生成されたトークンを逐次クライアントに送ることで、ユーザーはリアルタイムに応答が表示されるような体験を得られます。</p>
<p><code>src/index.ts</code> を以下のように変更します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#75715e">// ... (Envインターフェースは同じ)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">default</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>: <span style="color:#66d9ef">Request</span>, <span style="color:#a6e22e">env</span>: <span style="color:#66d9ef">Env</span>, <span style="color:#a6e22e">ctx</span>: <span style="color:#66d9ef">ExecutionContext</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">Response</span>&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> { <span style="color:#a6e22e">searchParams</span> } <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">prompt</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">searchParams</span>.<span style="color:#66d9ef">get</span>(<span style="color:#e6db74">&#39;prompt&#39;</span>) <span style="color:#f92672">||</span> <span style="color:#e6db74">&#34;What is streaming?&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// env.AI.runのオプションに stream: true を追加
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">stream</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;@cf/meta/llama-3-8b-instruct&#39;</span>,
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">prompt</span>: <span style="color:#66d9ef">prompt</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">stream</span>: <span style="color:#66d9ef">true</span>, <span style="color:#75715e">// ストリーミングを有効化
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      }
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// レスポンスのContent-Typeを &#39;text/event-stream&#39; に設定
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">stream</span>, {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;text/event-stream&#39;</span> },
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></td></tr></table>
</div>
</div><p>変更点は、<code>env.AI.run</code> のオプションに <code>stream: true</code> を追加し、レスポンスの<code>Content-Type</code>を<code>text/event-stream</code>に変更しただけです。これだけで、Workers AIはServer-Sent Events（SSE）形式で応答をストリーミングしてくれます。</p>
<h3 id="2-対話履歴を考慮したチャットボットを構築する">2. 対話履歴を考慮したチャットボットを構築する</h3>
<p>より自然な対話を実現するには、過去のやり取りをコンテキストとしてLLMに渡す必要があります。<code>prompt</code> の代わりに <code>messages</code> 配列を使用することで、これを簡単に実現できます。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">messages</span> <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// システムプロンプトでAIの役割を定義
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  { <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;system&#39;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;あなたは親切でユーモアのあるアシスタントです。&#39;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 過去のユーザーの発言
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  { <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;user&#39;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;一番面白いジョークを教えて。&#39;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 過去のAIの応答
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  { <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;assistant&#39;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;なぜ自転車は倒れないのでしょうか？…それは、two-tired（疲れている/タイヤが2つ）だからです！&#39;</span> },
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 今回のユーザーの発言
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  { <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;user&#39;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;うーん、別のを教えて。&#39;</span> }
</span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;@cf/meta/llama-3-8b-instruct&#39;</span>,
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">messages</span>: <span style="color:#66d9ef">messages</span>, <span style="color:#75715e">// promptの代わりにmessagesを使用
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  }
</span></span><span style="display:flex;"><span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// ...
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>実際のアプリケーションでは、この<code>messages</code>配列をCloudflare D1（サーバーレスDB）やKV（キーバリューストア）に保存し、ユーザーごとに管理することで、連続した対話が可能な本格的なチャットボットを構築できます。</p>
<h3 id="3-kvを使って高頻度のリクエストをキャッシュする">3. KVを使って高頻度のリクエストをキャッシュする</h3>
<p>「今日の天気は？」のような頻繁に来る同じ質問に対して、毎回LLMを呼び出すのはコストと時間の無駄です。Cloudflare KVを使えば、一度生成した応答をキャッシュし、2回目以降はキャッシュから高速に返すことができます。</p>
<p><code>wrangler.toml</code> にKVの設定を追加します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#75715e"># ...</span>
</span></span><span style="display:flex;"><span>[[<span style="color:#a6e22e">kv_namespaces</span>]]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">binding</span> = <span style="color:#e6db74">&#34;AI_CACHE&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">id</span> = <span style="color:#e6db74">&#34;YOUR_KV_NAMESPACE_ID&#34;</span> <span style="color:#75715e"># wrangler kv:namespace create AI_CACHE で作成</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>そして、<code>src/index.ts</code> でキャッシュロジックを実装します。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#75715e">// ... (EnvにKVの型定義を追加)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Env</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">AI</span>: <span style="color:#66d9ef">Ai</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">AI_CACHE</span>: <span style="color:#66d9ef">KVNamespace</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">default</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>: <span style="color:#66d9ef">Request</span>, <span style="color:#a6e22e">env</span>: <span style="color:#66d9ef">Env</span>, <span style="color:#a6e22e">ctx</span>: <span style="color:#66d9ef">ExecutionContext</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">Response</span>&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ... (promptの取得)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// KVからキャッシュを探す
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">cacheKey</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`prompt:</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">prompt</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">cachedResponse</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI_CACHE</span>.<span style="color:#66d9ef">get</span>(<span style="color:#a6e22e">cacheKey</span>, { <span style="color:#66d9ef">type</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;json&#39;</span> });
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">cachedResponse</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#34;Cache HIT!&#34;</span>);
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">cachedResponse</span>), {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span> },
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#34;Cache MISS. Calling AI...&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// キャッシュがなければAIを呼び出す
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">aiResponse</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(<span style="color:#75715e">/* ... */</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 結果をKVに保存（有効期限60分）
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// ctx.waitUntil()でレスポンス返却後も非同期処理を継続させる
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">waitUntil</span>(<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI_CACHE</span>.<span style="color:#a6e22e">put</span>(<span style="color:#a6e22e">cacheKey</span>, <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">aiResponse</span>), { <span style="color:#a6e22e">expirationTtl</span>: <span style="color:#66d9ef">3600</span> }));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">aiResponse</span>), {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span> },
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></td></tr></table>
</div>
</div><p>この実装により、同じプロンプトに対しては60分間、AIを呼び出すことなくキャッシュから即座に応答を返すことができ、コスト削減とパフォーマンス向上を両立できます。</p>
<h2 id="まとめ">まとめ</h2>
<p>本記事では、Cloudflare Workers AIという革新的なプラットフォームを用いて、最新のLLMであるLlama 3をエッジで実行する方法を、具体的なチュートリアルと実践的なTipsを交えて解説しました。</p>
<p><strong>Workers AIの登場は、AIアプリケーション開発の常識を覆すものです。</strong></p>
<p>かつては専門家チームと潤沢な予算がなければ手が出せなかったAI推論環境が、今や個人開発者でも <code>wrangler deploy</code> という一つのコマンドで、全世界に低遅延かつスケーラブルな形で展開できるようになりました。これは、AI活用の民主化における大きな一歩です。</p>
<p>もちろん、Workers AIにも制約はありますが、そのシンプルさ、パフォーマンス、そしてコスト効率は、特にユーザー向けのインタラクティブな機能開発において絶大な威力を発揮します。</p>
<p>今日学んだ知識を元に、ぜひあなた自身のアイデアを形にしてみてください。AIを使った要約機能、コンテンツ生成アシスタント、インテリジェントなチャットボット…可能性は無限大です。</p>
<p>サーバーレスAIの時代は、まだ始まったばかりです。Cloudflare Workers AIを使いこなし、次世代のアプリケーションを創造する旅に、今すぐ出発しましょう！</p>
]]></content:encoded>
      <category>Edge AI</category>
      <category>Cloudflare</category>
      <category>Workers AI</category>
      <category>Llama</category>
    </item>
  </channel>
</rss>
