プロジェクトの内容
Amazon Bedrockの生成AIを活用した、VBAマクロコードを自動的にフォーマットするWebアプリケーション。インデント、変数名、コメントなどを統一的なルールで整形します。
機能概要
- VBAコードのフォーマット
- インデントの自動調整
- 変数名の標準化
- コメントの追加
- ヘッダー・フッターの挿入
技術スタック
- Node.js
- Express.js
- HTML/CSS/JavaScript
必要要件
- Node.js (v14以上)
- npm (v6以上)
セットアップ手順
- プロジェクト構成ファイルを作成
- 依存パッケージのインストール
npm install
- 開発サーバーの起動
npm run dev
- ブラウザでアクセス
http://localhost:3000
プロジェクト構成
vba-formatter/
├── src/
│ ├── index.js # メインサーバーファイル
│ ├── formatter.js # 基本的なフォーマット処理
│ ├── bedrock/ # Bedrock関連の新規ディレクトリ
│ │ ├── client.js # Bedrock クライアント設定
│ │ ├── prompts.js # プロンプトテンプレート
│ │ └── analyzer.js # コード分析ロジック
│ └── public/ # フロントエンド
Bedorock関連
.env
AWS_ACCESS_KEY_ID=あなたのアクセスキー
AWS_SECRET_ACCESS_KEY=あなたのシークレットキー
AWS_REGION=us-east-1
dotenv
は、.env
ファイルを読み込んで、その内容を環境変数としてprocess.env
に設定するためのパッケージです。
npm install dotenv
@aws-sdk/client-bedrock-runtime
: Amazon Bedrockと通信するため下記インストール
npm install dotenv @aws-sdk/client-bedrock-runtime
client.js
:Amazon Bedrockへの接続設定require('dotenv').config();
const { BedrockRuntimeClient } = require("@aws-sdk/client-bedrock-runtime");
// Bedrockクライアントの設定
const client = 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
}
});
module.exports = client;
prompts.js
:AIへの指示(プロンプト)テンプレート/**
* prompts.js
* AIへの指示内容を定義するファイル
* VBAコードの分析と改善の方法をAIに指示します
*/
// AIへの指示内容を定義(バッククォートで囲むことで複数行の文字列を作成)
const ANALYSIS_PROMPT = `
# ここからがAIへの指示内容です
=============================================
# AIの役割定義
あなたはVBAコードの専門家として、以下のコードを分析し、優先順位に従って改善してください。
# 入力コード部分
\`\`\`vba
{code}
\`\`\`
# 改善要件(優先順位:高 - 第一弾)
=============================================
1. インデント処理
- SUBからENDSUBまでTABひとつ分のインデント
- IF文、With文、For文等の制御構造にもインデント
- ネストレベルに応じて適切なインデント
2. ヘッダー・フッター追加
- Sub開始時のヘッダー:
Option Explicit
'***************************************************
' [プロシージャ名]
'***************************************************
'【機 能】[機能の説明]
'【引 数】[引数の説明]
'【戻 り 値】[戻り値の説明]
'【機能説明】[詳細な説明]
'【備 考】[その他特記事項]
' Copyright(c) 2024 Your Company All Rights Reserved.
'***************************************************
- 処理の区切り:
'***************************************************
' 変数宣言
'***************************************************
[変数宣言部分]
- Sub終了時のフッター:
'***************************************************
'---------------------------------------------------
' Version
'---------------------------------------------------
' 1.00 | 2024.01.01 | ********* | *********
'***************************************************
# 改善要件(優先順位:中 - 第二弾)
=============================================
3. 変数名の改善
- 一文字の変数を禁止
- セル参照の変数は意味のある名前に変更
(例: Last_Row, Last_Column)
- 配列はArrayを付ける
- その他の変数はDataを付ける
4. Public変数・Call文の処理
- Public変数にはPublic関数であることをコメントで記載
- Call文にはモジュール名を追加
(例: Call Module1.印刷)
5. 変数宣言のコメント
- 宣言した変数の横にコメントを追加
- 使用目的や内容を簡潔に説明
# 改善要件(優先順位:中 - 第三弾)
=============================================
6. 変数・シート名の処理
- 日本語変数名を英語に変更
- 未宣言変数を「変数宣言」セクションに追加
- 型判定できない変数はVariantに
- シート名は定数(Const)で定義
- シート追加時の名前はVariantで処理
7. コメント追加
- IF文、With文などの制御構造にコメント
- 配列の内容説明
- SET文の説明
- Offsetのコメント必須
(参照セルと目的を明記)
8. コードの最適化
- 類似コードが3回以上続く場合はループ化
- パスの直書きは避け、pathに置換
(元のパスはコメントとして保持)
# 出力形式
=============================================
優先順位の高い要件(第一弾)から順に適用し、
改善したVBAコードのみを出力してください。
`;
module.exports = {
ANALYSIS_PROMPT
};
analyzer.js
:Bedrockとの通信処理// AWS SDKからBedrockのクライアントとコマンドをインポート
const { InvokeModelCommand } = require("@aws-sdk/client-bedrock-runtime");
const client = require('./client');
const { ANALYSIS_PROMPT } = require('./prompts');
/**
* VBAコードをClaudeモデルで分析する関数
* @param {string} vbaCode - 分析対象のVBAコード
* @returns {Promise<string>} - 改善されたVBAコード
*/
async function analyzeCode(vbaCode) {
try {
// プロンプトテンプレートにVBAコードを挿入
const prompt = ANALYSIS_PROMPT.replace('{code}', vbaCode);
// Claude用のリクエストコマンドを作成
const command = new InvokeModelCommand({
// Claude 3 Sonnetモデルを指定
modelId: "anthropic.claude-3-sonnet-20240229-v1:0",
contentType: "application/json",
accept: "application/json",
// Claude用のリクエスト形式
body: JSON.stringify({
anthropic_version: "bedrock-2023-05-31",
max_tokens: 2048,
messages: [
{
role: "user",
content: prompt
}
]
})
});
// BedrockAPIを呼び出し
const response = await client.send(command);
// レスポンスの処理(Claude形式)
const responseBody = Buffer.from(response.body).toString('utf8');
const jsonResponse = JSON.parse(responseBody);
// Claudeのレスポンス形式から結果を抽出
if (jsonResponse.content && jsonResponse.content[0]) {
return jsonResponse.content[0].text;
}
throw new Error('AIモデルからの応答が不正な形式です');
} catch (error) {
console.error("コード分析エラー:", error);
throw error;
}
}
module.exports = {
analyzeCode
};
メインファイル
src/index.js
:Webサーバーのメイン処理// ========================================
// サーバーのメインファイル (index.js)
// VBAフォーマッターのバックエンド処理を担当
// ========================================
// 必要なモジュールのインポート
const express = require('express');
const { analyzeCode } = require('./bedrock/analyzer'); // Bedrock AIの分析機能
const { formatVBA } = require('./formatter'); // 基本的なフォーマット機能
const { ANALYSIS_PROMPT } = require('./bedrock/prompts'); // AIプロンプトの取得
// Expressアプリケーションの初期化
const app = express();
// ミドルウェアの設定
// 静的ファイル(HTML/CSS/JS)の提供設定
app.use(express.static('src/public'));
// JSONリクエストの解析を有効化
app.use(express.json());
/**
* AIへのプロンプト内容を提供するエンドポイント
* フロントエンドでAIへの指示内容を表示するために使用
*/
app.get('/prompts', (req, res) => {
res.json({
success: true,
prompt: ANALYSIS_PROMPT
});
});
/**
* VBAコード分析API
* フロントエンドから送信されたコードを分析・改善
*/
app.post('/format', async (req, res) => {
try {
// リクエストからコードを取得
const { code } = req.body;
// 入力チェック
if (!code) {
return res.status(400).json({
success: false,
error: 'コードが提供されていません'
});
}
// 1. 基本的なフォーマットを適用
const basicFormatted = formatVBA(code);
// 2. AIによる高度な分析と改善
const aiAnalysis = await analyzeCode(basicFormatted);
// 成功時のレスポンス
res.json({
success: true,
formatted: aiAnalysis
});
} catch (error) {
// エラー発生時の処理
console.error('エラーが発生しました:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});
// サーバーの起動設定
const PORT = process.env.PORT || 3000;
// 全てのIPアドレスからのアクセスを許可(社内ネットワーク用)
app.listen(PORT, '0.0.0.0', () => {
console.log('========================================');
console.log(`VBA Formatter サーバー起動`);
console.log(`http://localhost:${PORT}`);
console.log('========================================');
});
フロントエンド
public/index.html
:ユーザーインターフェース<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字エンコーディングとビューポートの設定 -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VBA Formatter</title>
<!-- reset.css ress -->
<link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap" rel="stylesheet">
<!-- スタイルシートの読み込み -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- メインコンテナ -->
<div class="container">
<h1>VBA Formatter</h1>
<!-- AIへの指示内容表示セクション(src/bedrock/prompts.jsの内容) -->
<div class="prompt-section">
<h3>AIへの指示内容</h3>
<!-- プロンプト内容を動的に表示する要素 -->
<div class="prompt-display-container">
<div class="user-icon"></div>
<div class="prompt-display-wrapper">
<pre class="prompt-display">ユーザーからの指示内容がここに表示されます</pre>
</div>
</div>
</div>
<!-- コードエディタ部分 -->
<div class="editors">
<!-- 入力用エディタ -->
<div class="editor">
<h3>分析するコード</h3>
<!-- 入力用テキストエリア:ユーザーがコードを入力または貼り付け可能 -->
<textarea id="input" placeholder="VBAコードを入力してください"></textarea>
<!-- ファイル選択ボタン:.basと.txtファイルのみ受付 -->
<input type="file" id="vbaFile" accept=".bas,.txt">
<!-- <span class="detail">※.basと.txtファイルのみ受付</span> -->
</div>
<!-- 出力用エディタ -->
<div class="editor">
<h3>改善後のコード</h3>
<!-- 出力用テキストエリア:読み取り専用で改善されたコードを表示 -->
<textarea id="output" readonly></textarea>
<!-- フォーマット実行ボタン -->
<button onclick="formatCode()">Format</button>
</div>
</div>
</div>
<!-- JavaScriptの処理 -->
<script>
// ページ読み込み時にプロンプト内容を取得
window.onload = async function() {
try {
const response = await fetch('/prompts');
const data = await response.json();
if (data.success) {
document.querySelector('.prompt-display').textContent = data.prompt;
}
} catch (error) {
console.error('プロンプト取得エラー:', error);
document.querySelector('.prompt-display').textContent = 'プロンプトの読み込みに失敗しました';
}
};
/**
* コードのフォーマットを実行する関数
* 1. 入力を取得
* 2. サーバーにリクエスト
* 3. 結果を表示
*/
async function formatCode() {
// テキストエリアから入力を取得
const input = document.getElementById('input').value;
// ステータス表示用の要素取得
const formatButton = document.querySelector('button');
// 入力値のバリデーション
if (!input) {
alert('VBAコードを入力してください');
return;
}
// 処理開始のステータス表示
formatButton.innerHTML = '<span class="processing"><span></span><span></span><span></span></span>';
try {
// サーバーへのリクエスト
const response = await fetch('/format', {
method: 'POST', // POSTメソッドを使用
headers: {
'Content-Type': 'application/json' // JSONデータとして送信
},
body: JSON.stringify({ code: input }) // 入力をJSONに変換
});
// レスポンスの処理
const data = await response.json();
// 成功時は結果を表示、失敗時はエラーメッセージを表示
if (data.success) {
document.getElementById('output').value = data.formatted;
formatButton.textContent = '分析完了!';
} else {
formatButton.textContent = 'エラー: ' + data.error;
}
} catch (error) {
// 通信エラーなどの例外処理
formatButton.textContent = 'エラー: ' + error.message;
}
formatButton.classList.remove('processing'); // アニメーションクラスを削除
}
/**
* ファイル選択時の処理
* 選択されたファイルの内容を入力エリアに表示
*/
document.getElementById('vbaFile').addEventListener('change', (e) => {
// 選択されたファイルを取得
const file = e.target.files[0];
if (file) {
// FileReaderを使用してファイルの内容を読み込み
const reader = new FileReader();
// ファイル読み込み完了時の処理
reader.onload = (e) => {
// 読み込んだ内容を入力エリアに設定
document.getElementById('input').value = e.target.result;
};
// ファイルをテキストとして読み込み開始
reader.readAsText(file);
}
});
</script>
</body>
</html>
public/style.css
:見た目の装飾body {
font-family: "Noto Sans JP", serif;
background-color: #f1f2f3;
}
/* メインコンテナ */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem 2rem;
}
h1 {
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
letter-spacing: 0.1em;
padding: 1rem 0;
margin: 0 calc(50% - 50vw);
width: 100vw;
margin-bottom: 2rem;
}
h3 {
margin-bottom: 1rem;
text-align: center;
letter-spacing: .1em;
}
/* AIへの指示内容表示部分 */
.prompt-section {
margin-bottom: 2rem;
}
.prompt-display-container {
display: flex;
align-items: end;
justify-content: center;
gap: 2rem;
margin: 0 auto;
}
.user-icon {
width: 40px;
height: 40px;
background-color: #f6ce55;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 3rem;
position: relative;
}
.user-icon::after {
content: "";
position: absolute;
top: 96%;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 40px;
background-color: #f6ce55;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-top-left-radius: 50%;
border-top-right-radius: 50%;
}
.prompt-display-wrapper {
max-width: 80%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 5rem 5rem 5rem 0;
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
padding: 2rem;
}
.prompt-display {
font-family: monospace;
font-size: 0.825rem;
line-height: 1.5;
white-space: pre-wrap;
height: 300px;
overflow-y: scroll;
resize: vertical;
}
/* カスタムスクロールバーのスタイル */
.prompt-display::-webkit-scrollbar {
width: 0.5rem; /* スクロールバーの幅 */
}
.prompt-display::-webkit-scrollbar-thumb {
background: #888;
border-radius: 1rem;
}
/* エディタ部分 */
.editors {
display: flex;
gap: 2rem;
margin-bottom: 1rem;
}
.editor {
flex: 1;
display: flex;
flex-direction: column;
}
.editor > * {
margin-bottom: 1rem;
}
.editor > *:last-child {
margin-top: auto!important;
}
.editor input {
height: 3rem;
background-color: #ccc;
padding: 0.5rem 1rem;
border-radius: 4px;
width: 100%;
transition: all 0.3s ease;
}
.editor input:hover {
background-color: #bbb;
}
.editor .detail {
margin-top: 0.5rem;
color: #FF565D;
}
/* テキストエリア */
.editor textarea {
width: 100%;
height: 500px;
font-family: monospace;
padding: 10px;
font-size: 14px;
line-height: 1.5;
border: 2px solid #ccc;
background-color: #fff;
border-radius: 4px;
}
button {
height: 3rem;
padding: 0.5rem 1rem;
background-color: #e9be3b;
;
border-radius: 4px;
color: white;
letter-spacing: 0.1em;
border: none;
cursor: pointer;
}
button:hover {
background-color: #d3b458;
;
transition: all 0.3s ease;
}
/* アニメーションを追加するクラス */
.processing {
display: inline-flex;
gap: 0.5rem;
}
.processing span {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
background-color: #fff;
border-radius: 50%;
animation: fadeDots 1.5s infinite ease-in-out;
}
/* それぞれのドットに異なるアニメーションの遅延を設定 */
.processing span:nth-child(1) {
animation-delay: 0s;
}
.processing span:nth-child(2) {
animation-delay: 0.2s;
}
.processing span:nth-child(3) {
animation-delay: 0.4s;
}
/* 薄さ(透明度)を変化させるアニメーション */
@keyframes fadeDots {
0%, 100% { opacity: 0.2; } /* 薄くなる */
50% { opacity: 1; } /* 濃くなる */
}
その他
formatter.js
:VBAコードの基本的な整形処理
// VBAコードをフォーマットする関数
// 引数:code - フォーマットする元のVBAコードの文字列
// 戻り値:フォーマット済みのVBAコードの文字列
function formatVBA(code) {
// ステップ1: コードを行単位に分割
// splitは文字列を指定した区切り文字(ここでは改行)で配列に分割する
const lines = code.split('\n');
// ステップ2: インデントレベルを管理する変数を初期化
// インデントレベルは、コードのネストの深さを表す
// 例:Sub内なら1、If文の中なら2、というように増えていく
let indentLevel = 0;
// ステップ3: フォーマット済みの行を格納する配列を準備
const formattedLines = [];
// ステップ4: キーワードを定義
// これらの単語が行の先頭にあるかどうかでインデントを判断する
const startKeywords = ['sub', 'function', 'if', 'for', 'do'];
const endKeywords = ['end sub', 'end function', 'end if', 'next', 'loop'];
// ステップ5: 各行を処理
// forEachは配列の各要素に対して処理を行う
lines.forEach((line, lineNumber) => {
// 行の空白を削除して、小文字に変換(比較用)
const trimmedLine = line.trim();
const lowerLine = trimmedLine.toLowerCase();
// ステップ6: 空行の処理
if (trimmedLine === '') {
formattedLines.push('');
return; // 次の行の処理へ
}
// ステップ7: インデントレベルの調整
// 7.1: ブロックの終了を示すキーワードの前にインデントを減らす
if (endKeywords.some(keyword => lowerLine.startsWith(keyword))) {
indentLevel = Math.max(0, indentLevel - 1);
}
// ステップ8: 行のフォーマット
// 8.1: 現在のインデントレベルに応じてスペースを追加
// repeat()は文字列を指定回数繰り返す
const indent = ' '.repeat(indentLevel);
// 8.2: コメントの処理
// シングルクォートで始まる行はコメント
if (trimmedLine.startsWith("'")) {
formattedLines.push(indent + trimmedLine);
} else {
// 8.3: 通常のコードの処理
formattedLines.push(indent + trimmedLine);
}
// ステップ9: 次の行のためのインデントレベルの更新
// 9.1: ブロックの開始を示すキーワードの後でインデントを増やす
if (startKeywords.some(keyword => lowerLine.startsWith(keyword))) {
indentLevel++;
}
});
// ステップ10: フォーマット済みの行を改行文字で結合して1つの文字列に戻す
return formattedLines.join('\n');
}
// ステップ11: ヘッダーコメントを生成する関数
function createHeader() {
return [
"Option Explicit",
"'***************************************************",
"' VBAプログラム",
"'***************************************************",
"'【機 能】",
"'【返 り 値】なし",
"'【機能説明】",
"'【備 考】",
"' Copyright(c) " + new Date().getFullYear(),
"'***************************************************",
""
].join('\n');
}
// ステップ12: 変数をチェックして適切な型を提案する関数
function suggestVariableType(variableName) {
// 変数名から型を推測
if (variableName.toLowerCase().includes('count')) {
return 'Long';
} else if (variableName.toLowerCase().includes('date')) {
return 'Date';
} else if (variableName.toLowerCase().includes('flag')) {
return 'Boolean';
} else if (variableName.toLowerCase().includes('name')) {
return 'String';
} else {
return 'Variant';
}
}
// ステップ13: モジュールの外部公開
// このファイルの関数を他のファイルから使用できるようにする
module.exports = {
formatVBA,
createHeader,
suggestVariableType
};
プロジェクト設定ファイル
package.json
:依存パッケージの管理
{
"name": "vba-formatter",
"version": "1.0.0",
"description": "VBA Code Formatter",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"dependencies": {
"@aws-sdk/client-bedrock-runtime": "^3.712.0",
"dotenv": "^16.4.7",
"express": "^4.18.2",
"multer": "^1.4.5-lts.1"
},
"devDependencies": {
"nodemon": "^3.0.2"
}
}
test-connection.js:正しく動作するかテスト
require('dotenv').config();
const { BedrockRuntimeClient, InvokeModelCommand } = require("@aws-sdk/client-bedrock-runtime");
async function testBedrock() {
console.log("環境変数確認:");
console.log("Region:", process.env.AWS_REGION);
console.log("Access Key ID exists:", !!process.env.AWS_ACCESS_KEY_ID);
console.log("Secret Access Key exists:", !!process.env.AWS_SECRET_ACCESS_KEY);
const client = 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
}
});
// モデルごとに適切なリクエスト本文を生成する関数
function getRequestBody(modelId) {
if (modelId.startsWith('amazon.titan')) {
return {
inputText: "Hello",
textGenerationConfig: {
maxTokenCount: 10,
temperature: 0.7,
topP: 1
}
};
} else if (modelId.startsWith('anthropic')) {
return {
anthropic_version: "bedrock-2023-05-31",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Hello, Claude!"
}
]
};
}
}
// テストするモデルのリスト
const modelIds = [
// Titan Models(動作確認済み)
"amazon.titan-text-express-v1",
"amazon.titan-text-lite-v1",
// Mistral Models
"mistral.mistral-7b-instruct-v0:2",
"mistral.mistral-large-2402-v1:0",
"mistral.mistral-large-2407-v1:0",
"mistral.mistral-small-2402-v1:0",
"mistral.mixtral-8x7b-instruct-v0:1",
// Claude Models
"anthropic.claude-3-sonnet-20240229-v1:0", // Claude 3 Sonnet
"anthropic.claude-3-haiku-20240307-v1:0", // Claude 3 Haiku
"anthropic.claude-3-opus-20240229-v1:0", // Claude 3 Opus
"anthropic.claude-3-5-haiku-20241022-v1:0", // Claude 3.5 Haiku
"anthropic.claude-3-5-sonnet-20241022-v2:0",// Claude 3.5 Sonnet v2
"anthropic.claude-3-5-sonnet-20240620-v1:0",// Claude 3.5 Sonnet
"anthropic.claude-v2:1", // Claude 2.1
"anthropic.claude-v2", // Claude 2
"anthropic.claude-instant-v1" // Claude Instant
];
// 各モデルをテスト
for (const modelId of modelIds) {
console.log(`\nテスト: ${modelId}`);
try {
const command = new InvokeModelCommand({
modelId: modelId,
contentType: "application/json",
accept: "application/json",
body: JSON.stringify(getRequestBody(modelId))
});
const response = await client.send(command);
console.log(`✅ ${modelId} は利用可能です`);
// レスポンスの内容を表示
const responseBody = Buffer.from(response.body).toString('utf8');
console.log('応答:', responseBody);
} catch (error) {
console.log(`❌ ${modelId}: ${error.message}`);
}
}
}
testBedrock();
node test-connection.js
使用方法
- Webブラウザで http://localhost:3000 にアクセス
- テキストエリアにVBAコードを貼り付け、または.basファイルを選択
- 「Format」ボタンをクリック
- 右側のテキストエリアにフォーマット済みコードが表示
要件定義
### VBA Formatter with Amazon Bedrock プロジェクト説明
#### プロジェクト概要
このプロジェクトはJavaScript言語でNode.jsを利用し、ExpressというWebアプリケーションフレームワークで作成されています。VBAコードを改善するためにAmazon BedrockのAIを活用しています。
#### ファイル構成と役割
1. `src/public/index.html`
- Webブラウザで表示されるユーザーインターフェース
- VBAコードの入力とAI改善結果の表示を担当
2. `src/index.js`
- サーバープログラムのメインファイル
- ブラウザからのリクエストを処理
- AIとの連携を管理
3. `src/bedrock/prompts.js`
- AIへの指示内容(プロンプト)を定義
- コードの改善ルールを記述
4. `src/bedrock/analyzer.js`
- Amazon BedrockのAIと通信
- AIからの応答を処理
#### 処理の流れ
1. ブラウザでVBAコードを入力
2. サーバーがコードを受け取り
3. AIに分析を依頼
4. 改善されたコードが表示
#### 改善点
これまでAWSコンソールのAmazon Bedrockプレイグラウンドでチャット形式で行っていたAIとの対話を、使いやすいWebインターフェースで実現。以下が改善されました:
- コードの入力が簡単に
- AIへの指示内容が明確に表示
- 結果の表示が見やすく
- 複数のコードを連続して処理可能
#### 拡張性
- AIへの指示内容(プロンプト)を簡単に更新可能
- 新しい改善ルールの追加が容易
- チーム固有のコーディングルールも組み込み可能
#### 今後の展開
- より詳細なコード分析機能の追加
- チーム固有のルールの組み込み
- バッチ処理機能の追加
要確認
formatter.jsで生成A使用しない処理を使用できていない
改善項目
AWS SDK の追加活用
- CloudWatch Logs: AIの応答ログを収集・分析
- S3: VBAコードのバージョン管理や履歴保存
- DynamoDB: 変換履歴や頻出パターンの保存
UI
- 差分表示機能(基本的なnpmパッケージで実現可能)
vercelで公開
ExpressがNext.jsではないのにスムーズな理由は:
- Vercelは「Next.jsのためのプラットフォーム」ではなく
- 「モダンなWebアプリケーションのためのプラットフォーム」
- ExpressもNode.jsアプリケーションとして自然にサポート
- @vercel/nodeが複雑な変換を全て自動化
このため、ExpressアプリケーションでもNext.jsと同じようにスムーズにデプロイできるのです。
- @vercel/node
デプロイフロー
vercel.jsonの作成
vercel.jsonは、Vercelにデプロイする際の設定ファイルです。
vercel.json
{
"version": 2,
"builds": [
{
"src": "src/index.js",
"use": "@vercel/node"
},
{
"src": "src/public/**",
"use": "@vercel/static"
}
],
"routes": [
{
"src": "/prompts",
"dest": "/src/index.js"
},
{
"src": "/format",
"dest": "/src/index.js"
},
{
"src": "/api/(.*)",
"dest": "/src/index.js"
},
{
"src": "/(.+\\.[a-zA-Z]+)$",
"dest": "/src/public/$1"
},
{
"src": "/(.*)",
"dest": "/src/public/index.html"
}
]
}
.gitignore
node_modules
.env
.env.local
.DS_Store
GitHubにリポジトリを作成
vercel.com にGitHubアカウントでログイン
GitHubリポジトリをインポート
.envの内容を「Environment Variables」設定
Deployで公開完了