開発者向けポートフォリオサービス「Brightfolio」の核心機能として、AWS BedrockのClaude APIを活用したGitHubリポジトリの自動分析機能を実装しました。
この機能により、開発者のコードを自動で解析し、技術スタック、プロジェクトの特徴、改善提案まで含む詳細なレポートを生成しています。実際に私のポートフォリオ(daisuke-matsuura.brightfolio.link)でも、AI生成された分析結果を確認できます。
今回は、この AI 分析機能の技術的な実装方法と、開発過程で得た知見をお話しします。
なぜAWS Bedrockを選んだのか
OpenAI APIとの比較検討
当初はOpenAI GPT-4での実装も検討しましたが、最終的にAWS Bedrockを選択した理由は以下の通りです:
AWS Bedrockの優位点:
- 多様なモデル選択肢: Claude、Llama、Titanなど複数のLLMを統一APIで利用可能
- コスト効率: 大量処理時のトークン単価がOpenAI比で約30%削減
- フォールバック戦略: 複数モデルの組み合わせでサービス安定性向上
- プロンプトキャッシュ: 繰り返し処理でのコスト最適化
Claudeモデルの特徴
特にAnthropic社のClaudeモデルは、コード解析タスクにおいて優秀な性能を発揮:
- 長文コンテキスト: 最大200K トークンで大規模リポジトリにも対応
- 構造化出力: JSON形式での一貫した回答生成
- 技術的理解: プログラミング言語やフレームワークの深い理解
技術実装の詳細
Bedrockクライアントの初期化
import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";
// AWS Bedrockクライアントの初期化
const bedrockClient = new BedrockRuntimeClient({
region: process.env.AWS_REGION || "us-east-1",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
});
モデル選択とフォールバック戦略
複数のClaudeモデルを順番に試行することで、サービスの可用性を確保:
// 利用可能なモデルを優先順位で定義
const modelIds = [
"anthropic.claude-3-7-sonnet-20250219-v1:0", // 最新の Claude 3.7 Sonnet
"anthropic.claude-3-5-sonnet-20241022-v2:0", // Claude 3.5 Sonnet
"anthropic.claude-3-5-sonnet-20240620-v1:0", // 旧バージョン
"anthropic.claude-3-haiku-20240307-v1:0", // 軽量版(フォールバック)
];
// モデルを順番に試行
for (let modelIndex = 0; modelIndex < modelIds.length; modelIndex++) {
const modelId = modelIds[modelIndex];
try {
const command = new InvokeModelCommand({
modelId,
body: JSON.stringify(modelInput),
contentType: "application/json",
accept: "application/json",
});
const response = await bedrockClient.send(command);
// 成功した場合の処理
return parseResponse(response);
} catch (error) {
console.error(`Model ${modelId} failed:`, error);
// 次のモデルを試行
continue;
}
}
リトライ機能と指数バックオフ
API呼び出しの信頼性向上のため、指数バックオフによるリトライ機能を実装:
let retryCount = 0;
const maxRetries = 3;
while (retryCount < maxRetries) {
try {
const response = await bedrockClient.send(command);
return response;
} catch (error) {
retryCount++;
if (retryCount >= maxRetries) {
throw error;
}
// 指数バックオフで再試行
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, retryCount) * 1000)
);
}
}
プラン別プロンプト戦略
Brightfolioでは、ユーザープランに応じて異なる分析深度を提供しています。
Freeプラン: シンプル概要生成
const freePrompt = `
あなたはソフトウェアプロジェクトの厳格な評価者です。
以下の情報を基に、プロジェクトの概要を日本語で50字程度で記述してください。
- プロジェクト名: ${repoFullName}
- 主要技術: ${technologies}
客観的で、改善の余地がある点も含めて評価してください。
`;
特徴:
- 文字数制限: 50字程度
- 基本情報のみ使用
- シンプルな評価
Starterプラン: 機能分析付き
const starterPrompt = `
あなたはソフトウェアプロジェクトの客観的な評価者です。
分析結果を基に、プロジェクトの概要を日本語で150字程度で生成してください。
## リポジトリ情報
- プロジェクト名: ${repoFullName}
- プロジェクトタイプ: ${projectType}
- 主要技術: ${technologies}
- フレームワーク: ${frameworks}
## 分析結果のハイライト
${highlights.map(h => `- ${h}`).join('\\n')}
技術的な強みと改善の余地がある点の両方を評価してください。
`;
特徴:
- 文字数制限: 150字程度
- プロジェクトタイプ分析
- ハイライト機能
Proプラン: 技術負債分析
const proPrompt = `
あなたはソフトウェアプロジェクトの技術負債分析とコード品質評価の専門家です。
## 分析の重点項目
1. プロジェクト概要と技術的価値
2. 技術負債の詳細分析
3. 具体的な改善アクションプラン
4. ポートフォリオとしての価値
## 技術負債詳細分析
- 複雑度リスク: ${complexityRisk}
- テスト戦略: ${testStrategy}
- ドキュメント状況: ${documentationStatus}
- 依存関係管理: ${dependencyManagement}
構造化された技術負債分析を含む包括的な概要を500字程度で生成してください。
`;
特徴:
- 文字数制限: 500字程度
- 技術負債分析
- 改善提案
- 構造化された出力
プロンプトキャッシュによるコスト最適化
AWS Bedrockのプロンプトキャッシュ機能を活用して、API呼び出しコストを大幅削減:
const cachedPrompt = `
<prompt_cache>
あなたはソフトウェアプロジェクトの技術評価専門家です。
リポジトリの詳細な分析結果を基に、日本語でアプリケーション概要を生成してください。
分析観点:
- アプリケーションの目的と主要機能
- 使用技術スタックの特徴と適切性
- プロジェクトの技術的な価値や特色
- 開発者のスキルレベルと成長の証拠
- 改善の余地がある点と具体的な提案
</prompt_cache>
// 以下、プロジェクト固有の情報
プロジェクト名: ${repoFullName}
主要技術: ${technologies}
...
`;
効果:
- 繰り返し部分のトークン消費が約90%削減
- レスポンス時間の短縮
- 月間API費用が約40%削減
エラーハンドリングと運用監視
包括的なエラー分類
try {
const response = await bedrockClient.send(command);
return parseResponse(response);
} catch (error) {
// エラーの種類に応じた適切な処理
if (error.message.includes("rate limit")) {
return { error: "レート制限に達しました", retryAfter: 3600 };
}
if (error.message.includes("model not available")) {
// 次のモデルにフォールバック
continue;
}
if (error.message.includes("content policy")) {
return { error: "コンテンツポリシー違反が検出されました" };
}
// 予期しないエラー
throw new Error("AI分析中に予期しないエラーが発生しました");
}
トークン使用量の監視
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
// トークン使用量を記録
const tokenUsage = {
prompt: responseBody.usage?.input_tokens || 0,
completion: responseBody.usage?.output_tokens || 0,
model: modelId
};
console.log(`Tokens used - Prompt: ${tokenUsage.prompt}, Completion: ${tokenUsage.completion}`);
// データベースに使用量を保存(コスト分析用)
await saveTokenUsage(userId, tokenUsage);
実装で苦労したポイント
1. モデル可用性の変動
問題: Bedrockの新しいモデルが地域によって利用できない
最新のClaude 3.7 Sonnetをus-east-1で利用しようとしたところ、時折「ModelNotAvailableException」が発生しました。
解決策: フォールバック戦略の実装
// 地域とモデルの組み合わせを事前に検証
const availableModels = await validateModelsAvailability();
const modelIds = availableModels.filter(model =>
model.region === process.env.AWS_REGION
);
2. プロンプトトークン制限の管理
問題: 大規模リポジトリの解析時にトークン上限に到達
数千行のコードを含むリポジトリを分析する際、Claudeの200Kトークン制限に引っかかることがありました。
解決策: 段階的な情報圧縮
// コード量に応じて情報を圧縮
const compressAnalysisData = (analysisResult, maxTokens) => {
if (estimateTokens(analysisResult) > maxTokens) {
// ハイライトを最重要項目に絞る
analysisResult.highlights = analysisResult.highlights.slice(0, 3);
// 詳細なコード例を除去
delete analysisResult.codeExamples;
}
return analysisResult;
};
3. レスポンス形式の一貫性確保
問題: モデルによって出力形式が微妙に異なる
同じプロンプトでも、Claude 3.5と3.7で出力形式に差が生じることがありました。
解決策: 厳密なスキーマ検証
const validateResponse = (responseText) => {
// JSON形式の強制
const cleanedResponse = responseText
.replace(/```json\n?/, '')
.replace(/```\n?$/, '')
.trim();
try {
const parsed = JSON.parse(cleanedResponse);
return validateSchema(parsed);
} catch (error) {
// パースエラーの場合は再生成
throw new Error("Invalid response format");
}
};
パフォーマンス最適化の取り組み
非同期処理による高速化
// リポジトリ解析とAI分析を並行実行
const [analysisResult, repositoryMetadata] = await Promise.all([
analyzer.analyze(repoFullName),
fetchRepositoryMetadata(repoFullName)
]);
// AI概要生成は別プロセスで実行(ノンブロッキング)
generateApplicationSummary(analysisResult, repoFullName, planId)
.then(summary => saveSummaryToDatabase(summary))
.catch(error => logError("Summary generation failed", error));
キャッシュ戦略の実装
// 7日間のキャッシュでAPI呼び出しを削減
const checkCache = async (repoFullName, userId) => {
const { data: cachedAnalysis } = await supabase
.from("repository_analysis")
.select("*")
.eq("profile_id", userId)
.eq("repository_full_name", repoFullName)
.single();
if (cachedAnalysis &&
new Date(cachedAnalysis.expires_at) > new Date()) {
return cachedAnalysis.analysis_result;
}
return null;
};
運用開始後の課題と改善
コスト管理の最適化
初期の課題: 想定以上のAPI利用料金
月間のBedrock利用料金が当初予算の3倍に達し、急遽コスト削減策を実装しました。
改善策:
- プラン別制限: 無料ユーザーは月3回まで
- キャッシュ期間延長: 7日 → 30日に延長
- プロンプト最適化: 不要な説明文を削除して30%短縮
分析精度の向上
フィードバック分析: ユーザーからの「分析が表面的」との指摘
初期のプロンプトは汎用的すぎて、プロジェクト固有の特徴を捉えきれていませんでした。
改善策:
- 技術別プロンプト: React、Node.js、Pythonなど技術別に特化
- ドメイン認識: Webアプリ、CLI、ライブラリなど用途別分析
- 段階的詳細化: 概要 → 詳細 → 改善提案の3段階プロンプト
スケーラビリティ対応
// 同時実行数制限でAPI負荷を制御
const analysisQueue = new Queue('ai-analysis', {
concurrency: 3, // 同時実行3件まで
defaultJobOptions: {
removeOnComplete: 10,
removeOnFail: 5,
attempts: 3,
backoff: 'exponential'
}
});
analysisQueue.process(async (job) => {
const { repoFullName, userId, planId } = job.data;
return await performAIAnalysis(repoFullName, userId, planId);
});
今後の展開
多言語対応
現在は日本語のみですが、英語、中国語への対応を計画:
const generateMultiLanguageSummary = async (analysisResult, language = 'ja') => {
const prompts = {
'ja': japanesePrompt,
'en': englishPrompt,
'zh': chinesePrompt
};
return await generateSummary(analysisResult, prompts[language]);
};
リアルタイム分析
WebSocketを使用したリアルタイム進捗表示:
// 分析進捗をリアルタイム配信
const updateProgress = async (userId, progress) => {
await supabase
.channel(`analysis-${userId}`)
.send({
type: 'broadcast',
event: 'progress',
payload: progress
});
};
カスタム分析ルール
企業向けに独自の分析基準を設定可能な機能:
// 企業固有の評価基準
const customAnalysisRules = {
security: ['dependency-check', 'secret-scan'],
performance: ['bundle-size', 'lighthouse-score'],
maintainability: ['test-coverage', 'documentation']
};
まとめ
AWS BedrockとClaudeを活用したGitHubリポジトリ分析機能の実装により、以下の成果を得ることができました:
技術的成果:
- 複数モデルのフォールバック戦略で99.5%の可用性を実現
- プロンプトキャッシュにより40%のコスト削減
- プラン別分析機能で収益化モデルを確立
ビジネス成果:
- ユーザーの分析利用率が80%向上
- 有料プランへのコンバージョン率が15%に到達
- 月間API費用を予算内に収めることに成功
学んだこト:
- AI機能の実装は技術とビジネスの両面での戦略が重要
- フォールバック機能による可用性確保の重要性
- ユーザーフィードバックに基づく継続的な改善の必要性
AWS Bedrockは、個人開発でも本格的なAI機能を実装できる強力なプラットフォームです。特に複数モデルの活用による安定性と、プロンプトキャッシュによるコスト効率は、サービス運営において大きなメリットとなりました。
今後も技術の進歩に合わせて、より高精度で有用な分析機能を提供していきたいと思います。
関連リンク
この記事が役に立ったら、BrightfolioでAI分析機能を体験してみてください!GitHubリポジトリの詳細な分析レポートを自動生成できます。
コメント