AIチャット機能をRorkアプリに組み込んでみたものの、応答が返ってくるまでに3〜5秒かかってしまい、ユーザーが途中で離れてしまう——そんな経験をお持ちの方は少なくないのではないでしょうか。
OpenAIやAnthropicのAPIはどれも優秀ですが、推論速度という点でどうしても限界があります。その課題を一気に解決してくれるのが Groq API です。Groqは独自のLPU(Language Processing Unit)と呼ばれるチップでLLMの推論を行うことで、他のプロバイダーと比較して数倍〜数十倍の速度でテキストを生成できます。私自身、初めてGroqのレスポンスを見たとき「APIが壊れているのでは?」と疑ったくらい速くて驚きました。
Groq APIとは何か
GroqはAI推論の速度に特化したクラウドサービスです。2024年から急速に注目を集め、Llama 3、Mixtral、Gemma 2などのオープンソースモデルを、驚異的な速さで実行できます。
技術的なポイントは「LPU」と呼ばれる専用チップにあります。GPUが汎用的な行列演算に強いのに対し、LPUはLLMの自己回帰的なトークン生成に最適化されています。結果として、通常のGPU推論と比べて生成速度が大幅に向上し、ストリーミング表示のときにその差が特に顕著に現れます。
料金体系も開発者にやさしく、無料枠でも十分に試せる点も魅力のひとつです。
Groq APIキーの取得とセットアップ
まず console.groq.com にアクセスしてアカウントを作成します。Googleアカウントでのサインアップが最も手軽です。
ダッシュボードから「API Keys」を選択し、新しいキーを発行してください。発行したキーは一度しか表示されないため、安全な場所にメモしておきましょう。
Rorkでの管理については、APIキーはコードに直書きせず、環境変数として管理することを強くおすすめします。RorkからExpoのプロジェクト設定へアクセスし、app.config.js の extra フィールドか、.env ファイルで管理してください。
// .env ファイル(.gitignoreに必ず追加)
EXPO_PUBLIC_GROQ_API_KEY=YOUR_GROQ_API_KEYコード例では YOUR_GROQ_API_KEY のようなプレースホルダーを使いますが、実際の開発では環境変数から取得する実装にしてください。
Rorkで基本的なAIチャット機能を実装する
それでは、実際にRorkアプリへ組み込む実装を見ていきましょう。Groq APIはOpenAI互換のインターフェースを持っているため、openai パッケージをそのまま使えます。Rorkのプロンプトに「openai パッケージを使ってGroq APIへリクエストする」と指示するとスムーズです。
// src/lib/groq.js
import OpenAI from 'openai';
// Groq APIはOpenAI互換インターフェースを提供している
const groq = new OpenAI({
apiKey: process.env.EXPO_PUBLIC_GROQ_API_KEY,
baseURL: 'https://api.groq.com/openai/v1',
dangerouslyAllowBrowser: true, // Expoクライアントからの呼び出し用
});
export async function askGroq(messages) {
try {
const response = await groq.chat.completions.create({
model: 'llama3-8b-8192', // 高速なLlama 3 8Bモデル
messages,
max_tokens: 1024,
temperature: 0.7,
});
// 応答テキストを返す
return response.choices[0]?.message?.content ?? '応答を取得できませんでした';
} catch (error) {
// エラーの種類に応じて分岐
if (error.status === 429) {
throw new Error('リクエスト数の上限に達しました。少し時間をおいてから再試行してください。');
}
if (error.status === 401) {
throw new Error('APIキーが無効です。設定を確認してください。');
}
throw new Error(`Groq APIエラー: ${error.message}`);
}
}このコードの特徴は、baseURL をGroqのエンドポイントに切り替えるだけで、OpenAI SDKをそのまま流用できる点です。モデルの切り替えや既存のOpenAI実装からの移行もほとんど変更なしに行えます。
ストリーミング応答でリアルタイム表示を実現する
Groqの真価が発揮されるのはストリーミング実装です。トークンが生成されるたびにリアルタイムで表示することで、ユーザーは応答を「待つ」のではなく「読み始める」体験になります。
// src/components/ChatScreen.jsx
import React, { useState, useRef } from 'react';
import { View, Text, TextInput, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
import OpenAI from 'openai';
const groq = new OpenAI({
apiKey: process.env.EXPO_PUBLIC_GROQ_API_KEY,
baseURL: 'https://api.groq.com/openai/v1',
dangerouslyAllowBrowser: true,
});
export default function ChatScreen() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [isStreaming, setIsStreaming] = useState(false);
const scrollRef = useRef(null);
const sendMessage = async () => {
if (\!input.trim() || isStreaming) return;
const userMessage = { role: 'user', content: input };
const newMessages = [...messages, userMessage];
// ユーザーメッセージをすぐに表示
setMessages(newMessages);
setInput('');
setIsStreaming(true);
// アシスタントの応答枠を先に追加(空文字で初期化)
setMessages(prev => [...prev, { role: 'assistant', content: '' }]);
try {
const stream = await groq.chat.completions.create({
model: 'llama3-8b-8192',
messages: newMessages,
stream: true, // ストリーミングを有効化
max_tokens: 1024,
});
// チャンクが届くたびに最後のメッセージを更新
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content ?? '';
if (delta) {
setMessages(prev => {
const updated = [...prev];
updated[updated.length - 1] = {
role: 'assistant',
content: updated[updated.length - 1].content + delta,
};
return updated;
});
// スクロールを自動追従
scrollRef.current?.scrollToEnd({ animated: false });
}
}
} catch (error) {
setMessages(prev => {
const updated = [...prev];
updated[updated.length - 1] = {
role: 'assistant',
content: `エラーが発生しました: ${error.message}`,
};
return updated;
});
} finally {
setIsStreaming(false);
}
};
return (
<View style={styles.container}>
<ScrollView ref={scrollRef} style={styles.chatArea}>
{messages.map((msg, i) => (
<View key={i} style={[styles.bubble, msg.role === 'user' ? styles.user : styles.assistant]}>
<Text style={styles.text}>{msg.content}</Text>
</View>
))}
</ScrollView>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
value={input}
onChangeText={setInput}
placeholder="メッセージを入力..."
editable={\!isStreaming}
multiline
/>
<TouchableOpacity
style={[styles.sendButton, isStreaming && styles.disabled]}
onPress={sendMessage}
disabled={isStreaming}
>
<Text style={styles.sendText}>{isStreaming ? '...' : '送信'}</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#f5f5f5' },
chatArea: { flex: 1, padding: 12 },
bubble: { maxWidth: '80%', borderRadius: 12, padding: 10, marginBottom: 8 },
user: { backgroundColor: '#007AFF', alignSelf: 'flex-end' },
assistant: { backgroundColor: '#fff', alignSelf: 'flex-start' },
text: { color: '#333', fontSize: 15, lineHeight: 22 },
inputRow: { flexDirection: 'row', padding: 8, backgroundColor: '#fff', borderTopWidth: 1, borderTopColor: '#eee' },
input: { flex: 1, borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 8, marginRight: 8, maxHeight: 100 },
sendButton: { backgroundColor: '#007AFF', borderRadius: 8, paddingHorizontal: 16, justifyContent: 'center' },
disabled: { backgroundColor: '#aaa' },
sendText: { color: '#fff', fontWeight: 'bold' },
});このコードをそのままRorkに貼り付けて「このコードでチャット画面を作って」とプロンプトすると、実際に動くUIを生成してもらえます。for await...of によるストリーミング処理が核心部分で、チャンクが届くたびに最後のメッセージを更新しています。
利用可能なモデルと使い分け
Groqでは複数のモデルが利用できます。用途に応じて使い分けると、速度とコストのバランスが取りやすくなります。
- llama3-8b-8192: 最速かつ無料枠が広い。日常的な会話やシンプルなQ&Aに最適
- llama3-70b-8192: 精度重視。複雑な推論や長文生成が必要な場面に
- mixtral-8x7b-32768: コンテキストウィンドウが32Kと広い。長い会話履歴を保持したいアプリに向いている
- gemma2-9b-it: Google DeepMindのモデル。日本語の精度がやや高い傾向があります
アプリの要件に応じて model フィールドを切り替えるだけで比較できるので、まず llama3-8b-8192 で試してから調整するのが私のおすすめの進め方です。
エラーハンドリングとRate Limit対策
Groqの無料プランにはRate Limitがあります(モデルによって1分あたりのリクエスト数や生成トークン数に制限があります)。本番環境では以下の対策が効果的です。
// 指数バックオフを使ったリトライ実装
async function askGroqWithRetry(messages, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await askGroq(messages);
} catch (error) {
const isRateLimit = error.message.includes('上限に達しました');
if (isRateLimit && attempt < maxRetries - 1) {
// 1秒、2秒、4秒と待機時間を倍増する(指数バックオフ)
const waitTime = Math.pow(2, attempt) * 1000;
console.log(`Rate Limit — ${waitTime / 1000}秒後にリトライ (${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
throw error; // リトライ上限に達したら例外を再スロー
}
}
}本番アプリでは、クライアントから直接APIを呼ぶのではなく、バックエンド(Cloudflare WorkersやEdge Functions)を経由してAPIキーを隠す設計が安全です。Rorkでの外部API連携ガイドでそのパターンを詳しく解説しているので、あわせてご覧ください。
Groqを選ぶべき場面、他のAPIを選ぶべき場面
Groqは速度と無料枠の広さが魅力ですが、すべての用途に最適というわけではありません。私が実際にいくつかのアプリで使い分けてみた感触をお伝えします。
Groqが向いている場面:
- リアルタイムチャットや即座の応答が求められるアシスタント機能
- プロトタイプや開発初期の費用を抑えたい段階
- Llamaなどのオープンソースモデルを試したい場合
他のAPIの方が良い場面:
- 関数呼び出し(Function Calling)が重要なアプリはClaude APIやOpenAI APIの関数呼び出し機能の方が成熟しています
- 画像や音声などのマルチモーダル入力が必要な場合
- 独自ファインチューニングが必要な場面
どちらか一方に縛られる必要はなく、用途ごとに使い分けたり、Groqをプライマリ→レート制限時はOpenAIにフォールバックという構成も取れます。
まず1つ動かしてみることから始めましょう
Groq APIの最大の魅力は、今日すぐに試せることです。アカウント作成から最初のレスポンスを受け取るまで10分もかかりません。まずは簡単なチャット画面を1つ作って、その速度を体感してみてください。「速い」という体験が、次のアイデアにつながることが多いと感じています。
Rorkアプリ全体のAI機能設計についてはClaude APIを使ったAIアシスタントアプリの作り方も参考になります。Groqの速度とAnthropicの精度を組み合わせた構成を検討している方にはとくにおすすめです。