見出し画像

【必見】Claude 3.5 SonnetのArtifacts内でローカルLLM(Gemini nano)を無料実行!コードも完全公開

ClaudeのArtifacts内でGemini Nanoを使ってリアルタイム翻訳アプリを実行方法を解説します。コード付きです。

必要なもの

  • パソコン

  • Claudeの会員登録(無料版でOK)

  • Chrome Canaryのインストール(最新の機能が使える)

革命児、登場 - Claude 3.5 SonnetとArtifacts機能の衝撃

画像
安い・早い・強いの三拍子

皆さん、AIの世界で今、とんでもないことが起きているんです。その名も「Claude 3.5 Sonnet」。このAIモデル、ただ者じゃありません。特に注目なのが「Artifacts」という機能なんですが、これがまた曲者。

想像してみてください。あなたがアイデアを口にすると、目の前でコードが踊り出す。ウェブサイトのデザインが形になる。そう、まるで魔法のように。しかも、その場で修正もできちゃうんです。「ちょっと、この色変えてよ」なんて言えば、ホイっと変わっちゃう。

例えば、今までエンジニアリングの知見がなかったPMなどが、これを使えば頭の中にあるアイデアを形にできるわけです。

もちろんこの翻訳アプリも100%Claudeで書いていて、私は一切修正していません。

小さな巨人、Gemini nano登場!Googleの秘密兵器

画像
一番小さいナノモデル

一方、Googleも黙ってはいません。「Gemini nano」という小さな巨人を送り込んできました。

この子、すごいんです。スマホやタブレットで直接動くんですよ。しかも、ネットがなくてもOK。プライバシーを気にする人にはうってつけ。テキストを生成したり、画像を認識したり、音声を理解したり...まるでポケットの中に万能選手を忍ばせているような感じです。

例えば、海外旅行中に見つけた謎の料理。「これ何?」って聞くだけで、その場で教えてくれちゃう。オフラインでも使えるから、山奥でも大丈夫。冒険好きの人には、最高の相棒になりそうですね。

Artifacts×Gemini nano

さあ、ここからが本当の驚きです。なんと、Claude 3.5 SonnetのArtifacts機能を使って、Gemini nanoを動かすことができるんです!これって、まさに最強のAIコンビネーションじゃないですか?

でも、どうやってそんなことができるの?って思いますよね。実は、Artifacts機能の中でブラウザのAPIを使って、Gemini nanoを呼び出すことができるんです。これ、めちゃくちゃ画期的なんですよ!

想像してみてください。今までは安くはない金額を払って、OpenAIやClaudeのAPIを呼び出してAIアプリを開発していたわけです。

これを無料で好きなだけ呼び出せるなら最高じゃないですか?
しかもオフラインでも大丈夫なので、飛行機の中でももちろん大丈夫です。

Artifacts×Gemini nanoでリアルタイム翻訳

基本的には以下の3ステップで実行できます

1. Google Canaryをnpakaさんの記事を参考にインストール

私はM2 Macで行いました。

Chrome の Gemini Nano を試す

2. ClaudeのArtifacts機能を有効にする

画像
トップページから変更ができる

まず、Claude 3.5 Sonnetにアクセスして、Artifacts機能を有効にしましょう。次に、私が用意したコードをClaude 3.5 Sonnetに入力します。このコードは、ArtifactsとGemini nanoを連携させる魔法の呪文みたいなものです。

3. 「このコードをartifacts内で実行して」と頼む

画像
import React, { useState, useEffect, useRef } from 'react';
import { Loader2, ArrowRight } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Alert, AlertDescription } from "@/components/ui/alert";

const TranslationComponent = () => {
  // ステート変数の定義
  const [inputText, setInputText] = useState(''); // 入力テキスト
  const [translatedText, setTranslatedText] = useState(''); // 翻訳されたテキスト
  const [error, setError] = useState(''); // エラーメッセージ
  const [isLoading, setIsLoading] = useState(false); // ローディング状態
  const sessionRef = useRef(null); // AIセッションの参照
  const abortControllerRef = useRef(null); // リクエストのキャンセル用コントローラー

  // コンポーネントのマウント時にAIセッションを初期化
  useEffect(() => {
    const initializeSession = async () => {
      try {
        // ジェネリックセッションが作成可能かチェック
        const canCreate = await window.ai.canCreateGenericSession();
        if (canCreate !== "no") {
          // セッションを作成
          sessionRef.current = await window.ai.createTextSession();
        } else {
          setError("セッションを作成できません");
        }
      } catch (err) {
        setError("セッション初期化エラー: " + err.message);
      }
    };
    initializeSession();

    // クリーンアップ関数:コンポーネントのアンマウント時にセッションを破棄
    return () => {
      if (sessionRef.current) {
        sessionRef.current.destroy();
      }
    };
  }, []);

  // 入力テキストが変更されるたびに翻訳を実行
  useEffect(() => {
    const translateText = async () => {
      // 入力テキストが空の場合は翻訳をクリア
      if (!sessionRef.current || inputText.trim() === '') {
        setTranslatedText('');
        setIsLoading(false);
        return;
      }

      // 既存のリクエストがある場合はキャンセル
      if (abortControllerRef.current) {
        abortControllerRef.current.abort(); 
      }

      try {
        // 新しいAbortControllerを作成
        abortControllerRef.current = new AbortController();
        setError(''); 
        setTranslatedText('');
        setIsLoading(true);

        // 翻訳リクエストを送信
        const stream = sessionRef.current.promptStreaming(
          `Translate the following Japanese text to English: "${inputText}"`, 
          { signal: abortControllerRef.current.signal }
        );

        // ストリームから翻訳結果を受信
        for await (const chunk of stream) {
          // 翻訳テキストの前後の引用符を削除し、余分な空白を削除
          setTranslatedText(chunk.trim().replace(/^["']|["']$/g, ''));
        }
      } catch (err) {
        // AbortError以外のエラーの場合にエラーメッセージを設定
        if (err.name !== 'AbortError') { 
          setError("翻訳エラー: " + err.message);
        } 
      } finally {
        setIsLoading(false);
      }
    };

    translateText();

    // クリーンアップ関数:コンポーネントの再レンダリング時に実行中のリクエストをキャンセル
    return () => {
      if (abortControllerRef.current) { 
        abortControllerRef.current.abort();
      }
    };
  }, [inputText]);

  // 入力テキストの変更ハンドラ
  const handleInputChange = (e) => {
    setInputText(e.target.value);
  };

  // UIのレンダリング
  return (
    <div className="min-h-screen bg-gradient-to-br from-blue-100 to-purple-100 flex items-center justify-center p-4">
      <Card className="w-full max-w-md">
        <CardHeader>
          <CardTitle className="text-2xl font-bold text-center text-gray-800">リアルタイム翻訳</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {/* 日本語入力フィールド */}
          <div className="space-y-2">
            <label htmlFor="japaneseInput" className="text-sm font-medium text-gray-700">
              日本語テキスト
            </label>
            <Input
              id="japaneseInput"
              value={inputText}
              onChange={handleInputChange}
              placeholder="ここに入力してください..."
              className="w-full"
            />
          </div>
          {/* 矢印の区切り線 */}
          <div className="relative">
            <div className="absolute inset-0 flex items-center">
              <div className="w-full border-t border-gray-300" />
            </div>
            <div className="relative flex justify-center text-sm">
              <span className="px-2 bg-white text-gray-500">
                <ArrowRight className="w-6 h-6 text-blue-500" />
              </span>
            </div>
          </div>
          {/* 英語翻訳結果表示エリア */}
          <div className="space-y-2">
            <label className="text-sm font-medium text-gray-700">英語翻訳</label>
            <div className="w-full p-3 bg-gray-50 border border-gray-200 rounded-md min-h-[60px] text-gray-800 relative">
              {isLoading ? (
                <div className="absolute inset-0 flex items-center justify-center">
                  <Loader2 className="w-6 h-6 text-blue-500 animate-spin" />
                </div>
              ) : (
                translatedText
              )}
            </div>
          </div>
          {/* エラーメッセージ表示 */}
          {error && (
            <Alert variant="destructive">
              <AlertDescription>{error}</AlertDescription>
            </Alert>
          )}
        </CardContent>
      </Card>
    </div>
  );
};

export default TranslationComponent;

ほんとにこれだけです

入力した文章が、リアルタイムで英語に翻訳されるんです!
しかも、これ全部オフラインで行われているんですよ。すごくないですか?
試しにWifiをオフにしてみてください。

このガイドを読んで、「えっ、そんな簡単にできるの?」って思った人もいるかもしれません。でも、本当にそれくらい簡単なんです。AIの最先端技術を、まるでおもちゃで遊ぶように体験できる。そんな時代が、もう目の前に来ているんです。

無料で始められる、あなただけのAIプロダクト

最後に強調したいのが、これらの技術が基本的に無料で使えるということ。

今まで高額な費用がかかっていたAIアプリ開発が、誰でも気軽に始められるようになりました。

あなたの頭の中にあるアイデアを、すぐに形にできる。
そして、それを世界中の人々と共有できる。

これって、まさにAI革命の始まりじゃないでしょうか?


この記事が気に入ったらサポートをしてみませんか?

ピックアップされています

エンジニア

  • 703本

コメント

コメントを投稿するには、 ログイン または 会員登録 をする必要があります。
【必見】Claude 3.5 SonnetのArtifacts内でローカルLLM(Gemini nano)を無料実行!コードも完全公開|アヴィ
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1