llm-application-dev について
LLM アプリ開発向けのリファレンスで、プロンプト設計、API 呼び出し、RAG、エラー処理を扱います。キャッシュ、評価、プライバシーなど実装上の指針もまとめています。
主な機能
- 01構造化プロンプトと少数例
- 02OpenAI と Anthropic の API パターン
- 03ストリーミング応答の処理
- 04RAG、文書分割、埋め込み保存
- 05リトライとフォールバックによるエラー処理
- 06評価・キャッシュ・プライバシーの実践
活用シーン
- 01ルールと例を含むプロンプトの設計
- 02LLM API 接続とストリーミング出力の処理
- 03文書検索生成パイプラインの構築
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ moizibnyousaf/ ai-agent-skills --skill llm-application-devインストール後、Claude Code で/llm-application-devを入力して読み込まれたか確認します。
詳細
LLM アプリケーション開発
プロンプトエンジニアリング
構造化プロンプト
const systemPrompt = `You are a helpful assistant that answers questions about our product.
RULES:
- Only answer questions about our product
- If you don't know, say "I don't know"
- Keep responses concise (under 100 words)
- Never make up information
CONTEXT:
{context}`;
const userPrompt = `Question: {question}`;
少数ショットの例
const prompt = `Classify the sentiment of customer feedback.
Examples:
Input: "Love this product!"
Output: positive
Input: "Worst purchase ever"
Output: negative
Input: "It works fine"
Output: neutral
Input: "${customerFeedback}"
Output:`;
思考の連鎖
const prompt = `Solve this step by step:
Question: ${question}
Let's think through this:
1. First, identify the key information
2. Then, determine the approach
3. Finally, calculate the answer
Step-by-step solution:`;
API 統合
OpenAI パターン
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function chat(messages: Message[]): Promise<string> {
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages,
temperature: 0.7,
max_tokens: 500,
});
return response.choices[0].message.content ?? '';
}
Anthropic パターン
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
async function chat(prompt: string): Promise<string> {
const response = await anthropic.messages.create({
model: 'claude-3-opus-20240229',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
});
return response.content[0].type === 'text'
? response.content[0].text
: '';
}
ストリーミング応答
async function* streamChat(prompt: string) {
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) yield content;
}
}
RAG(検索拡張生成)
基本的な RAG パイプライン
async function ragQuery(question: string): Promise<string> {
// 1. Embed the question
const questionEmbedding = await embedText(question);
// 2. Search vector database
const relevantDocs = await vectorDb.search(questionEmbedding, { limit: 5 });
// 3. Build context
const context = relevantDocs.map(d => d.content).join('\n\n');
// 4. Generate answer
const prompt = `Answer based on this context:\n${context}\n\nQuestion: ${question}`;
return await chat(prompt);
}
ドキュメントのチャンク分割
function chunkDocument(text: string, options: ChunkOptions): string[] {
const { chunkSize = 1000, overlap = 200 } = options;
const chunks: string[] = [];
let start = 0;
while (start < text.length) {
const end = Math.min(start + chunkSize, text.length);
chunks.push(text.slice(start, end));
start += chunkSize - overlap;
}
return chunks;
}
埋め込みの保存
// Using Supabase with pgvector
async function storeEmbeddings(docs: Document[]) {
for (const doc of docs) {
const embedding = await embedText(doc.content);
await supabase.from('documents').insert({
content: doc.content,
metadata: doc.metadata,
embedding: embedding, // vector column
});
}
}
async function searchSimilar(query: string, limit = 5) {
const embedding = await embedText(query);
const { data } = await supabase.rpc('match_documents', {
query_embedding: embedding,
match_count: limit,
});
return data;
}
エラー処理
async function safeLLMCall<T>(
fn: () => Promise<T>,
options: { retries?: number; fallback?: T }
): Promise<T> {
const { retries = 3, fallback } = options;
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 429) {
// Rate limit - exponential backoff
await sleep(Math.pow(2, i) * 1000);
continue;
}
if (i === retries - 1) {
if (fallback !== undefined) return fallback;
throw error;
}
}
}
throw new Error('Max retries exceeded');
}
ベストプラクティス
- トークン管理:使用量を追跡し、上限を設定します
- キャッシュ:埋め込みと一般的なクエリをキャッシュします
- 評価:多様な入力でプロンプトをテストします
- ガードレール:使用前に出力を検証します
- ログ記録:デバッグ用にプロンプトと応答を記録します
- コスト管理:単純なタスクにはより安価なモデルを使用します
- レイテンシ:UX を向上させるため、応答をストリーミングします
- プライバシー:個人を特定できる情報(PII)を外部 API に送信しないでください
コメント
Markdown 対応