オープンなMLモデルを使用してWebアプリジェネレータを作成する
Create a web app generator using open ML models.
コード生成モデルがますます一般公開されるようになると、以前には想像もできなかった方法でテキストからウェブやアプリへの変換が可能になりました。
このチュートリアルでは、コンテンツのストリーミングとレンダリングを一度に行うことで、AIウェブコンテンツ生成への直接的なアプローチを紹介します。
ここでライブデモを試してみてください! → Webapp Factory
NodeアプリでのLLMの使用方法
AIやMLに関連するすべてのことをPythonで行うと思われがちですが、ウェブ開発コミュニティではJavaScriptとNodeに大いに依存しています。
このプラットフォームで大きな言語モデルを使用する方法をいくつか紹介します。
ローカルでモデルを実行する
JavaScriptでLLMを実行するためのさまざまなアプローチがあります。ONNXを使用したり、コードをWASMに変換して他の言語で書かれた外部プロセスを呼び出したりする方法などがあります。
これらの技術のいくつかは、次のような使いやすいNPMライブラリとして利用できます:
- コード生成をサポートするtransformers.jsなどのAI/MLライブラリの使用
- ブラウザ用のllama-node(またはweb-llm)など、専用のLLMライブラリの使用
- Pythoniaなどのブリッジを介してPythonライブラリを使用
ただし、このような環境で大きな言語モデルを実行すると、リソースをかなり消費することがあります。特にハードウェアアクセラレーションを使用できない場合はさらにリソースが必要です。
APIを使用する
現在、さまざまなクラウドプロバイダが言語モデルの使用を提案しています。以下はHugging Faceの提供するオプションです:
コミュニティから小さなモデルからVoAGIサイズのモデルまで使用できる無料の推論API。
より高度で本番向けの推論エンドポイントAPIで、より大きなモデルやカスタム推論コードが必要な方向けのもの。
これらの2つのAPIは、NPM上のHugging Face推論APIライブラリを使用してNodeから利用できます。
💡 パフォーマンスの高いモデルは一般的に多くのメモリ(32 Gb、64 Gb以上)とハードウェアアクセラレーションが必要です(ベンチマークを参照してください)。しかし、一部のタスクでは、メモリが16 Gbまたは8 Gb程度で要件が比較的低いままであるモデルのサイズが縮小していく傾向も見られます。
アーキテクチャ
NodeJSを使用してジェネレーティブAIウェブサーバーを作成します。
モデルはInferenceエンドポイントAPI上で動作するWizardCoder-15Bですが、他のモデルとスタックで試してみても構いません。
他のソリューションに興味がある場合は、以下の代替実装へのポインターをご覧ください:
- Inference APIを使用する:コードとスペース
- NodeからPythonモジュールを使用する:コードとスペース
- llama-node(llama cpp)を使用する:コード
プロジェクトの初期化
まず、新しいNodeプロジェクトをセットアップする必要があります(必要に応じてこのテンプレートをクローンすることもできます)。
git clone https://github.com/jbilcke-hf/template-node-express tutorial
cd tutorial
nvm use
npm install
次に、Hugging Face推論クライアントをインストールします:
npm install @huggingface/inference
そして、`src/index.mts`に設定します:
import { HfInference } from '@huggingface/inference'
// 実際のプロダクションではAPIトークンを安全に保つために、次のような方法を使用することが推奨されます:
// const hfi = new HfInference(process.env.HF_API_TOKEN)
const hfi = new HfInference('** YOUR TOKEN **')
推論エンドポイントの設定
💡 注意: このチュートリアルでエンドポイントインスタンスの料金を支払いたくない場合は、このステップをスキップし、代わりにこの無料の推論APIの例を参照してください。ただし、これは比較的パワフルではない小さなモデルでのみ動作します。
新しいエンドポイントをデプロイするには、エンドポイント作成ページに移動します。
モデルリポジトリのドロップダウンで`WizardCoder`を選択し、十分に大きなGPUインスタンスが選択されていることを確認する必要があります:
エンドポイントが作成されると、このページからURLをコピーできます:
クライアントを設定して使用します:
const hf = hfi.endpoint('** エンドポイントのURL **')
推論クライアントにプライベートエンドポイントを使用し、モデルを呼び出すことができます:
const { generated_text } = await hf.textGeneration({
inputs: '単純な「こんにちは、世界」のHTMLページ:<html><body>'
});
HTMLストリームを生成する
URLにアクセスしたときに、ウェブクライアントにいくつかのHTMLを返す時が来ました。例えば、/app
とします。
Express.jsを使用して、Hugging Face Inference APIからの結果をストリームするためのエンドポイントを作成します。
import express from 'express'
import { HfInference } from '@huggingface/inference'
const hfi = new HfInference('** あなたのトークン **')
const hf = hfi.endpoint('** エンドポイントのURL **')
const app = express()
現時点ではUIがないため、プロンプトのための単純なURLパラメータとしてインターフェースが提供されます:
app.get('/', async (req, res) => {
// ページの始めをブラウザに送信する(残りはAIによって生成されます)
res.write('<html><head></head><body>')
const inputs = `# タスク
${req.query.prompt}を生成する
# 出力
<html><head></head><body>`
for await (const output of hf.textGenerationStream({
inputs,
parameters: {
max_new_tokens: 1000,
return_full_text: false,
}
})) {
// 結果をブラウザにストリームする
res.write(output.token.text)
// デバッグのためにコンソールにも出力する
process.stdout.write(output.token.text)
}
req.end()
})
app.listen(3000, () => { console.log('サーバーが起動しました') })
ウェブサーバーを起動します:
npm run start
そして、https://localhost:3000?prompt=some%20prompt
を開きます。しばらくすると、いくつかの基本的なHTMLコンテンツが表示されるはずです。
プロンプトの調整
各言語モデルは、プロンプトに対して異なる反応を示します。WizardCoderの場合、シンプルな指示が最も適していることが多いです:
const inputs = `# タスク
${req.query.prompt}を生成する
# 注文
JSの<script></script>タグ内にアプリケーションロジックを書く。
すべてを<div class="flex flex-col items-center">でラップする中央のレイアウトを使用する。
# 出力
<html><head></head><body>`
Tailwindの使用
Tailwindは、コンテンツのスタイリングに人気のあるCSSフレームワークであり、WizardCoderはそれに適しています。
これにより、ページの最初や最後にスタイルシートを生成する必要がなくなります(ページが固まったように感じられるため)。
結果を改善するために、モデルによる指示を示すこともできます(<body class="p-4 md:p-8">
)。
const inputs = `# タスク
${req.query.prompt}を生成する
# 注文
TailwindCSSのユーティリティクラスを使用する(Tailwindは既にページにインジェクトされています)。
JSの<script></script>タグ内にアプリケーションロジックを書く。
すべてを<div class="flex flex-col items-center">でラップする中央のレイアウトを使用する。
# 出力
<html><head></head><body class="p-4 md:p-8">`
幻覚の防止
コード生成に特化した軽量なモデルでは、幻覚や失敗(全ての指示を繰り返したり、「lorem ipsum」というプレースホルダーテキストを書いたりすること)を信頼性を持って防ぐことは難しいことがあります。一方、より大規模な汎用モデルと比較すると、それを軽減するために試みることができます。
命令を実行するために命令形を使用し、命令を繰り返すことも効果的な方法です。また、一部の出力を英語で示すことによって方法を示すことも効率的な方法です:
const inputs = `# タスク
${req.query.prompt}を生成する
# 注文
これらの指示を繰り返すのではなく、最終コードを書くこと!
TailwindCSSのユーティリティクラスを使用する必要があります(Tailwindは既にページにインジェクトされています)!
アプリケーションロジックをJSの<script></script>タグ内に書いてください!
これはデモアプリではないので、英語を使用する必要があります。ラテン語ではなく、英語で書いてください!
すべてを包むために中央のレイアウトを使用して<div class="flex flex-col items-center">を書いてください
# 出力
<html><head><title>App</title></head><body class="p-4 md:p-8">`
画像のサポートを追加する
HTML、CSS、JSのコードを生成できるシステムがありますが、画像の生成を求められると、壊れたURLを幻覚する可能性があります。
幸いなことに、画像生成モデルを選ぶのには多くのオプションがあります!
→ 無料の推論APIを使用してハブで利用可能なパブリックモデルの1つを使用して、安定したディフュージョンモデルを呼び出す最速の方法は次のとおりです:
app.get('/image', async (req, res) => {
const blob = await hf.textToImage({
inputs: `${req.query.caption}`,
model: 'stabilityai/stable-diffusion-2-1'
})
const buffer = Buffer.from(await blob.arrayBuffer())
res.setHeader('Content-Type', blob.type)
res.setHeader('Content-Length', buffer.length)
res.end(buffer)
})
次の行をプロンプトに追加するだけで、WizardCoderに新しい/image
エンドポイントを使用するように指示することができます!(他のモデルに合わせて微調整する必要があるかもしれません):
キャプションから画像を生成するには、/image APIを呼び出してください:<img src="/image?caption=何かの写真と場所">
より具体的にすることもできます。たとえば:
数枚の画像を生成し、少なくとも10語以上の説明的な写真キャプションを使用してください!
UIの追加
Alpine.jsは、セットアップやビルドパイプライン、JSX処理などなしで対話型のUIを作成できるミニマリストのフレームワークです。
すべてがページ内で行われるため、クイックデモのUIを作成するのに最適です。
次の静的HTMLページを/public/index.html
に配置できます:
<html>
<head>
<title>チュートリアル</title>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="flex flex-col space-y-3 p-8" x-data="{ draft: '', prompt: '' }">
<textarea
name="draft"
x-model="draft"
rows="3"
placeholder="何かを入力してください.."
class="font-mono"
></textarea>
<button
class="bg-green-300 rounded p-3"
@click="prompt = draft">生成</button>
<iframe :src="`/app?prompt=${prompt}`"></iframe>
</div>
</body>
</html>
これを動作させるには、いくつかの変更を加える必要があります:
...
// localhost:3000にアクセスすると、/public/index.htmlからファイルが読み込まれます
app.use(express.static('public'))
// '/'から'/app'に変更しました
app.get('/app', async (req, res) => {
...
出力の最適化
これまでは、Tailwindのユーティリティクラスの完全なシーケンスを生成してきました。これは言語モデルにデザインの自由を与えるのに非常に便利です。
しかし、このアプローチは非常に冗長であり、トークンの割り当ての大部分を消費します。
出力をより密にするために、TailwindプラグインであるDaisy UIを使用することができます。Daisy UIはTailwindのユーティリティクラスをデザインシステムに整理するものです。アイデアは、コンポーネントには短縮クラス名を使用し、その他の部分にはユーティリティクラスを使用することです。
一部の言語モデルには、Daisy UIの内部知識がない場合があります。それはニッチなライブラリです。その場合、プロンプトにAPIドキュメンテーションを追加できます:
# DaisyUI ドキュメント
## レイアウトを作成するには、各記事を次のようにラップします:
<article class="prose"></article>
## 適切なCSSクラスを使用する
<button class="btn ..">
<table class="table ..">
<footer class="footer ..">
さらに進む
最終デモスペースには、ユーザーインターフェースのより完全な例が含まれています。
このコンセプトをさらに拡張するためのいくつかのアイデアを以下に示します:
- StarCoderなどの他の言語モデルをテストする
- 中間言語(React、Svelte、Vueなど)のファイルとコードを生成する
- 既存のフレームワーク(例:NextJS)内でコード生成を統合する
- 失敗または部分的なコード生成から回復する(例:JSの問題を自動修正する)
- チャットボットプラグインに接続する(例:チャットディスカッションに小さなWebアプリのiframeを埋め込む)
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles