ChatGPTにエクセルファイルをプロンプトに送り、感想などの返答をもらう:簡単なAPIでの実装コード
[HttpPost("FromExcel")] public async Task<string?> GetResult(IFormFile postedFile) { StringBuilder sb = new(); using var stream = postedFile.OpenReadStream(); var reader = ExcelReaderFactory.CreateOpenXmlReader(stream); while (reader.Read()) { for (int col = 0; col < reader.FieldCount; col++) { Debug.WriteLine(reader.GetValue(col)); sb.Append(reader.GetValue(col)); sb.Append(','); } sb.Append(System.Environment.NewLine); } return await GetChatGptResponse("以下のドキュメントについての感想をください" + sb.ToString()); } private async Task<string?> GetChatGptResponse(string prompt) { var openAiService = new OpenAIService(new OpenAiOptions() { ApiKey = "yourApiKey" }); Console.WriteLine(prompt); var result = await openAiService.Completions.CreateCompletion(new CompletionCreateRequest() { Prompt = prompt, Echo = false, MaxTokens = 300 // about }, Models.TextDavinciV3); if (result.Successful) { return result.Choices.Select(x => x.Text).FirstOrDefault(); } else return null; }
実践的には下記のようなものも必要
Excelファイルには様々なデータ形式が存在します。数値、文字列、日付、さらには数式など、異なる形式のデータが混在しているため、GetValue
メソッドで取得した値を適切に扱う必要があります。現在のコードではデータ型の処理がシンプルに扱われていますが、フォーマットごとに適切に処理することが求められます。
改善案:
null
の場合や、特定のフォーマットが必要な場合は、そのデータ型を明示的にチェックし、適切に処理するロジックを追加する。object value = reader.GetValue(col);
if (value != null)
{
if (value is DateTime)
sb.Append(((DateTime)value).ToString("yyyy-MM-dd"));
else if (value is double)
sb.Append(((double)value).ToString("F2"));
else
sb.Append(value.ToString());
}
APIキーをコードに直接書き込むのはセキュリティ上のリスクがあります。環境変数や設定ファイルを使用して、APIキーを安全に管理することが推奨されます。特にプロダクション環境では、APIキーが漏洩すると悪用される可能性があるため、適切なセキュリティ対策が必要です。
推奨方法:
appsettings.json
)に保存し、コードから直接参照しないようにする。var apiKey = Environment.GetEnvironmentVariable("OpenAiApiKey");
var openAiService = new OpenAIService(new OpenAiOptions()
{
ApiKey = apiKey
});
非同期処理を活用することで、特に大規模なExcelファイルを処理する際のパフォーマンスが向上します。しかし、データが多い場合にはメモリの消費が増加する可能性があるため、ストリーム処理やメモリ管理を適切に行うことが重要です。
改善案:
async
やawait
を活用した非同期処理を正しく実装し、レスポンスの高速化を図る。IAsyncEnumerable
を使用し、大量のデータを逐次処理する設計に変更することも検討。ファイルが正しくアップロードされたかどうかの検証が重要です。例えば、ファイルが空だったり、対応していない形式のファイルがアップロードされた場合に、適切なエラーメッセージを返す仕組みを追加することで、ユーザーの混乱を避けられます。
実装例:
if (postedFile == null || postedFile.Length == 0)
{
return BadRequest("ファイルがアップロードされていません。");
}
if (!postedFile.FileName.EndsWith(".xlsx"))
{
return BadRequest("サポートされていないファイル形式です。");
}
現在の実装では、エラーが発生した際にnull
を返していますが、より詳細なエラー情報をログに記録し、ユーザーに分かりやすいエラーメッセージを返すことで、デバッグや問題解決が容易になります。
改善案:
try-catch
ブロックを使って、例外が発生した場合に適切なエラーメッセージを記録し、ユーザーに返す。try
{
// Excelファイルの読み込みと処理
}
catch (Exception ex)
{
// ログにエラーを記録
_logger.LogError(ex, "Excelファイルの処理中にエラーが発生しました。");
return StatusCode(500, "内部エラーが発生しました。");
}
Excelファイルには複数のシートが含まれる場合があります。現在の実装では1つのシートしか処理していませんが、複数シートが存在する場合は、それぞれのシートを処理する機能を追加するとより柔軟です。
実装例:
ExcelReader
のNextResult()
メソッドを使って、次のシートに移動しながら全シートを処理する。do
{
while (reader.Read())
{
// 各行の処理
}
} while (reader.NextResult()); // 次のシートに移動
ChatGPTに送信するテキストの量が多くなると、トークン制限に引っかかる可能性があります。特に、Excelファイルの内容が大きい場合には、適切にテキストを分割して送信したり、トークン数を制御する必要があります。
改善案:
MaxTokens
で適切に設定し、応答が切れないようにする。