uploadService.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { IndexingConfig } from '../types';
  2. // web/services/uploadService.ts
  3. export const uploadService = {
  4. async uploadFile(file: File, authToken: string): Promise<any> {
  5. const formData = new FormData();
  6. formData.append('file', file);
  7. const response = await fetch('/api/upload', {
  8. method: 'POST',
  9. headers: {
  10. 'Authorization': `Bearer ${authToken}`,
  11. },
  12. body: formData,
  13. });
  14. if (!response.ok) {
  15. const errorData = await response.json();
  16. throw new Error(errorData.message || 'fileUploadFailed');
  17. }
  18. return response.json();
  19. },
  20. async uploadFileWithConfig(file: File, config: IndexingConfig, authToken: string): Promise<any> {
  21. const formData = new FormData();
  22. formData.append('file', file);
  23. formData.append('chunkSize', config.chunkSize.toString());
  24. formData.append('chunkOverlap', config.chunkOverlap.toString());
  25. formData.append('embeddingModelId', config.embeddingModelId);
  26. // 処理モードを追加(指定されている場合)
  27. if (config.mode) {
  28. formData.append('mode', config.mode);
  29. }
  30. const response = await fetch('/api/upload', {
  31. method: 'POST',
  32. headers: {
  33. 'Authorization': `Bearer ${authToken}`,
  34. },
  35. body: formData,
  36. });
  37. if (!response.ok) {
  38. const errorData = await response.json();
  39. throw new Error(errorData.message || 'fileUploadFailed');
  40. }
  41. return response.json();
  42. },
  43. async uploadText(content: string, title: string, config: IndexingConfig, authToken: string): Promise<any> {
  44. const response = await fetch('/api/upload/text', {
  45. method: 'POST',
  46. headers: {
  47. 'Content-Type': 'application/json',
  48. 'Authorization': `Bearer ${authToken}`
  49. },
  50. body: JSON.stringify({
  51. content,
  52. title,
  53. chunkSize: config.chunkSize.toString(),
  54. chunkOverlap: config.chunkOverlap.toString(),
  55. embeddingModelId: config.embeddingModelId,
  56. mode: config.mode
  57. })
  58. });
  59. if (!response.ok) {
  60. const errorData = await response.json().catch(() => ({}));
  61. throw new Error(errorData.message || 'noteIndexFailed');
  62. }
  63. return response.json();
  64. },
  65. /**
  66. * ファイル処理モードの推奨を取得
  67. * ファイルの種類、サイズなどの要因に基づいて、高速モードまたは高精度モードの使用を推奨します
  68. */
  69. async recommendMode(file: File): Promise<any> {
  70. // セーフティチェック
  71. if (!file || !file.name) {
  72. return {
  73. recommendedMode: 'fast',
  74. reason: 'invalidFile',
  75. warnings: ['incompleteFileInfo'],
  76. };
  77. }
  78. // フロントエンドの簡単な判定ロジック
  79. const ext = file.name.toLowerCase().split('.').pop();
  80. const sizeMB = file.size / (1024 * 1024);
  81. const preciseFormats = ['pdf', 'doc', 'docx', 'ppt', 'pptx'];
  82. const supportedFormats = [...preciseFormats, 'xls', 'xlsx', 'txt', 'md', 'html', 'json', 'csv'];
  83. if (!supportedFormats.includes(ext || '')) {
  84. return {
  85. recommendedMode: 'fast',
  86. reason: `unsupportedFileFormat`,
  87. reasonArgs: [ext],
  88. warnings: ['willUseFastMode'],
  89. };
  90. }
  91. if (!preciseFormats.includes(ext || '')) {
  92. return {
  93. recommendedMode: 'fast',
  94. reason: `formatNoPrecise`,
  95. reasonArgs: [ext],
  96. warnings: ['willUseFastMode'],
  97. };
  98. }
  99. // 小規模なファイルには高速モードを推奨
  100. if (sizeMB < 5) {
  101. return {
  102. recommendedMode: 'fast',
  103. reason: 'smallFileFastOk',
  104. estimatedCost: 0,
  105. estimatedTime: sizeMB * 2,
  106. warnings: [],
  107. };
  108. }
  109. // 中規模なファイルには高精度モードを推奨
  110. if (sizeMB < 50) {
  111. return {
  112. recommendedMode: 'precise',
  113. reason: 'mixedContentPreciseRecommended',
  114. estimatedCost: Math.max(0.01, sizeMB * 0.01),
  115. estimatedTime: sizeMB * 8,
  116. warnings: ['willIncurApiCost'],
  117. };
  118. }
  119. // 大規模なファイルには高精度モードを推奨するが警告を表示
  120. return {
  121. recommendedMode: 'precise',
  122. reason: 'largeFilePreciseRecommended',
  123. estimatedCost: sizeMB * 0.015,
  124. estimatedTime: sizeMB * 12,
  125. warnings: ['longProcessingTime', 'highApiCost', 'considerFileSplitting'],
  126. };
  127. },
  128. };