AtoX-Keisuke-Ogawa commited on
Commit
b266adb
·
1 Parent(s): f7b86b7

modified translation module to be able to reduce the number of request to API

Browse files
.gitignore CHANGED
@@ -12,4 +12,8 @@ __pycache__/
12
  env/
13
 
14
  translated_df.csv
15
- before_translate*
 
 
 
 
 
12
  env/
13
 
14
  translated_df.csv
15
+ before_translate*
16
+
17
+ *translated.xlsx
18
+ *translation_log.jsonl
19
+ *translations.json
app.py CHANGED
@@ -8,7 +8,7 @@ import io
8
  import pandas as pd
9
  from config.logger import logger
10
 
11
- def run_script(shop_id, environment, image_process_flag, spreadsheet_format_version, program_command):
12
  """main.py を実行し、ログを UI に表示"""
13
  log_output = []
14
 
@@ -21,7 +21,7 @@ def run_script(shop_id, environment, image_process_flag, spreadsheet_format_vers
21
  if program_command == 'main':
22
  command = ["python", "main.py", environment, image_process_flag, spreadsheet_format_version]
23
  elif program_command == 'translate':
24
- command = ["python", "translate_exe.py", spreadsheet_format_version]
25
  else:
26
  pass
27
 
@@ -56,13 +56,13 @@ def run_script(shop_id, environment, image_process_flag, spreadsheet_format_vers
56
 
57
  yield "\n".join(log_output)
58
 
59
- def download_csv(shop_id_input):
60
- df = pd.read_csv("translated_df.csv")
61
- output_file = "translated_df.csv"
62
- df.to_csv(output_file, index=False, encoding="utf-8-sig")
63
- if os.path.exists(output_file):
64
- logger.info('file exist')
65
- return output_file
66
 
67
  # Gradio UI の定義
68
  with gr.Blocks() as demo:
@@ -72,6 +72,7 @@ with gr.Blocks() as demo:
72
  environment_input = gr.Radio(["登録しない", "開発", "本番"], label="Select Environment", value="開発")
73
  image_copy_input = gr.Radio(["実行", "スキップ"], label="S3の画像コピー処理", value="実行")
74
  spreadsheet_format_version_input = gr.Radio(["v1", "v2"], label="スプレッドシートのフォーマットバージョン", value="v2")
 
75
 
76
  log_output = gr.Textbox(label="ログ", interactive=False, lines=15)
77
 
@@ -87,7 +88,8 @@ with gr.Blocks() as demo:
87
  environment_input,
88
  image_copy_input,
89
  spreadsheet_format_version_input,
90
- gr.State("main")
 
91
  ],
92
  outputs=[log_output]
93
  )
@@ -98,7 +100,8 @@ with gr.Blocks() as demo:
98
  environment_input,
99
  image_copy_input,
100
  spreadsheet_format_version_input,
101
- gr.State("translate")
 
102
  ],
103
  outputs=[log_output]
104
  )
 
8
  import pandas as pd
9
  from config.logger import logger
10
 
11
+ def run_script(shop_id, environment, image_process_flag, spreadsheet_format_version, program_command, batch_num):
12
  """main.py を実行し、ログを UI に表示"""
13
  log_output = []
14
 
 
21
  if program_command == 'main':
22
  command = ["python", "main.py", environment, image_process_flag, spreadsheet_format_version]
23
  elif program_command == 'translate':
24
+ command = ["python", "translate_exe.py", batch_num]
25
  else:
26
  pass
27
 
 
56
 
57
  yield "\n".join(log_output)
58
 
59
+ # def download_csv(shop_id_input):
60
+ # df = pd.read_csv("translated_df.csv")
61
+ # output_file = "translated_df.csv"
62
+ # df.to_csv(output_file, index=False, encoding="utf-8-sig")
63
+ # if os.path.exists(output_file):
64
+ # logger.info('file exist')
65
+ # return output_file
66
 
67
  # Gradio UI の定義
68
  with gr.Blocks() as demo:
 
72
  environment_input = gr.Radio(["登録しない", "開発", "本番"], label="Select Environment", value="開発")
73
  image_copy_input = gr.Radio(["実行", "スキップ"], label="S3の画像コピー処理", value="実行")
74
  spreadsheet_format_version_input = gr.Radio(["v1", "v2"], label="スプレッドシートのフォーマットバージョン", value="v2")
75
+ batch_num = gr.Textbox(label="AI翻訳のバッチ数", placeholder="例: 50")
76
 
77
  log_output = gr.Textbox(label="ログ", interactive=False, lines=15)
78
 
 
88
  environment_input,
89
  image_copy_input,
90
  spreadsheet_format_version_input,
91
+ gr.State("main"),
92
+ batch_num
93
  ],
94
  outputs=[log_output]
95
  )
 
100
  environment_input,
101
  image_copy_input,
102
  spreadsheet_format_version_input,
103
+ gr.State("translate"),
104
+ batch_num
105
  ],
106
  outputs=[log_output]
107
  )
domain/dish.py CHANGED
@@ -4,7 +4,7 @@ from config.variables import *
4
  from decimal import Decimal
5
 
6
  class Dish:
7
- def __init__(self, spreadsheet_format_version):
8
  self.spreadsheet_format_version = spreadsheet_format_version
9
  return
10
 
 
4
  from decimal import Decimal
5
 
6
  class Dish:
7
+ def __init__(self, spreadsheet_format_version="v1"):
8
  self.spreadsheet_format_version = spreadsheet_format_version
9
  return
10
 
domain/option.py CHANGED
@@ -5,7 +5,7 @@ from decimal import Decimal
5
  from domain.dish import Dish
6
 
7
  class Option:
8
- def __init__(self, spreadsheet_format_version):
9
  self.spreadsheet_format_version = spreadsheet_format_version
10
  return
11
 
 
5
  from domain.dish import Dish
6
 
7
  class Option:
8
+ def __init__(self, spreadsheet_format_version="v1"):
9
  self.spreadsheet_format_version = spreadsheet_format_version
10
  return
11
 
domain/translator.py CHANGED
@@ -32,3 +32,6 @@ class OpenAITranslator:
32
  )
33
  response = completion.choices[0].message.content
34
  return response
 
 
 
 
32
  )
33
  response = completion.choices[0].message.content
34
  return response
35
+
36
+ def create_description(self, text, target_language):
37
+ return
requirements.txt CHANGED
@@ -6,3 +6,4 @@ openpyxl
6
  gradio
7
  google-genai
8
  openai
 
 
6
  gradio
7
  google-genai
8
  openai
9
+ xlsxwriter
services/s3_manager.py CHANGED
@@ -46,6 +46,26 @@ class S3Manager:
46
  except Exception as e:
47
  logger.error(f"翻訳結果のアップロード失敗: {file_key}: {str(e)}", exc_info=True)
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  def delete_existing_image_files(self, target_bucket, target_prefix):
51
  # copy_images_by_dish_idを実行する前に、target_prefix内のフォルダとファイルを一旦全て削除する
 
46
  except Exception as e:
47
  logger.error(f"翻訳結果のアップロード失敗: {file_key}: {str(e)}", exc_info=True)
48
 
49
+
50
+ def upload_excel_to_s3(self, dishes_df: pd.DataFrame, options_df: pd.DataFrame, file_key: str):
51
+ """
52
+ 2つのDataFrameを1つのExcelファイルにまとめ、S3にアップロードする
53
+ """
54
+ try:
55
+ buffer = BytesIO()
56
+
57
+ # ExcelWriterで複数シート作成
58
+ with pd.ExcelWriter(buffer, engine='xlsxwriter') as writer:
59
+ dishes_df.to_excel(writer, sheet_name="料理", index=False)
60
+ options_df.to_excel(writer, sheet_name="オプション", index=False)
61
+
62
+ buffer.seek(0)
63
+
64
+ # S3にアップロード
65
+ self.s3.put_object(Bucket=self.bucket_name, Key=file_key, Body=buffer.getvalue())
66
+ logger.info(f"ExcelファイルをS3にアップロード成功: s3://{self.bucket_name}/{file_key}")
67
+ except Exception as e:
68
+ logger.error(f"Excelファイルのアップロード失敗: {file_key}: {str(e)}", exc_info=True)
69
 
70
  def delete_existing_image_files(self, target_bucket, target_prefix):
71
  # copy_images_by_dish_idを実行する前に、target_prefix内のフォルダとファイルを一旦全て削除する
translate_exe.py CHANGED
@@ -1,38 +1,276 @@
1
  import pandas as pd
 
 
 
 
2
  import os
3
- from domain.translator import GeminiTranslator, OpenAITranslator
4
- from services.translate_manager import DishTranslator
5
  from config.variables import *
 
 
6
  from logging import INFO, DEBUG
7
  from services.s3_manager import S3Manager
8
  logger.setLevel(INFO)
9
  pd.set_option('display.max_columns', None)
10
 
11
- from domain.dish import Dish
12
- # spreadsheet_format_version = sys.argv[3]
13
- spreadsheet_format_version = "v1"
14
- dish_inst = Dish(spreadsheet_format_version)
15
- df = dish_inst.get_df(excel)
16
- # df = dish_inst.get_df(excel).head(20)
17
- # df = pd.read_csv("/Users/keisukeogawa/Downloads/personal/AtoX/translate_tool_internal/before_translate2.csv")
18
-
19
- # gemini_api_key = os.getenv("GEMINI_API_KEY")
20
- # translator = GeminiTranslator(gemini_api_key)
21
- openai_api_key = os.getenv("OPENAI_API_KEY")
22
- translator = OpenAITranslator(openai_api_key)
23
-
24
- # DishTranslatorのイスタンスを作成
25
- df_translator = DishTranslator(df, translator)
26
-
27
- # DataFrameの翻訳を実行
28
- translated_df = df_translator.translate_columns()
29
- translated_df.to_csv('translated_df.csv', index=False, encoding='utf-8-sig')
30
- logger.info("exported translated_df.csv")
31
- # logger.info(translated_df)
32
-
33
- # CSVとしてS3に保存
34
- bucket_name = "operation-menu-boy"
35
- OUTPUT_FILE_KEY = f"{shop_id}/翻訳結果/{shop_id}_translated.csv"
36
-
37
- s3_manager = S3Manager(bucket_name)
38
- s3_manager.upload_df_to_s3(translated_df, OUTPUT_FILE_KEY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import pandas as pd
2
+ import json
3
+ import openai
4
+ from typing import Dict, List, Tuple
5
+ import time
6
  import os
7
+ import sys
 
8
  from config.variables import *
9
+ from domain.dish import Dish
10
+ from domain.option import Option
11
  from logging import INFO, DEBUG
12
  from services.s3_manager import S3Manager
13
  logger.setLevel(INFO)
14
  pd.set_option('display.max_columns', None)
15
 
16
+ # Replace with your actual OpenAI API key
17
+ openai.api_key = os.getenv("OPENAI_API_KEY")
18
+
19
+ # File paths
20
+ OUTPUT_FILE = "translated.xlsx"
21
+
22
+ def main():
23
+ # Load Excel sheets
24
+ logger.info("Loading Excel file...")
25
+ try:
26
+ # localで実行したい場合:
27
+ # INPUT_FILE = "/Users/keisukeogawa/Downloads/personal/AtoX/translate_tool_internal/before_translate3.xlsx"
28
+ # dishes_df = pd.read_excel(INPUT_FILE, sheet_name="料理")
29
+ # options_df = pd.read_excel(INPUT_FILE, sheet_name="オプショ")
30
+ dish_inst = Dish()
31
+ dishes_df = dish_inst.get_df(excel)
32
+ option_inst = Option()
33
+ options_df = option_inst.get_option_df(excel)
34
+ options_df = change_column_name(options_df)
35
+ logger.info(f"Loaded successfully: {len(dishes_df)} dishes and {len(options_df)} options")
36
+ except Exception as e:
37
+ logger.info(f"Error loading Excel file: {e}")
38
+ return
39
+
40
+ # Target columns for translation (Japanese columns only)
41
+ dish_translation_targets = [
42
+ "料理名", "カテゴリ名", "見出し名", "リード文", "説明文"
43
+ ]
44
+
45
+ option_translation_targets = [
46
+ "オプション名", "タイトル名", "リード文"
47
+ ]
48
+
49
+ # Target languages and their corresponding column suffixes
50
+ languages = {
51
+ "英語": "English",
52
+ # "韓国語": "Korean",
53
+ # "繁体字": "Traditional Chinese",
54
+ # "簡体字": "Simplified Chinese"
55
+ }
56
+
57
+ # Extract unique Japanese texts to translate
58
+ dish_texts = extract_unique_texts(dishes_df, dish_translation_targets, "料理")
59
+ option_texts = extract_unique_texts(options_df, option_translation_targets, "オプション")
60
+ unique_texts = list(set(dish_texts + option_texts))
61
+ logger.info(f"Found {len(unique_texts)} unique texts to translate")
62
+
63
+ # import pdb;pdb.set_trace()
64
+
65
+ # Translate all texts at once with a single API call
66
+ # translations = load_translations_from_json("translations.json")
67
+ translations = batch_translate_texts(unique_texts, languages)
68
+ save_translations_to_json(translations)
69
+
70
+ # Update dataframes with translations
71
+ update_dataframes_with_translations(dishes_df, translations, dish_translation_targets, languages, "料理")
72
+ update_dataframes_with_translations(options_df, translations, option_translation_targets, languages, "オプション")
73
+
74
+ # Save the translated data back to Excel
75
+ save_to_excel(dishes_df, options_df)
76
+ logger.info(f"Translations completed and saved to {OUTPUT_FILE}")
77
+
78
+ # Save excel file to S3
79
+ save_to_excel_and_upload_to_s3(dishes_df, options_df, shop_id)
80
+
81
+ def change_column_name(df: pd.DataFrame):
82
+ df.columns = [col.replace("(", "(").replace(")", ")") for col in df.columns]
83
+ rename_map = {
84
+ 'オプションタイトル(日本語)': 'オプション名(日本語)',
85
+ 'オプションタイトル(英語)': 'オプション名(英語)',
86
+ 'オプションタイトル(韓国語)': 'オプション名(韓国語)',
87
+ 'オプションタイトル(繁体字)': 'オプション名(繁体字)',
88
+ 'オプションタイトル(簡体字)': 'オプション名(簡体字)',
89
+ 'オプションバリュー(日本語)': 'タイトル名(日本語)',
90
+ 'オプションバリュー(英語)': 'タイトル名(英語)',
91
+ 'オプションバリュー(韓国語)': 'タイト���名(韓国語)',
92
+ 'オプションバリュー(繁体字)': 'タイトル名(繁体字)',
93
+ 'オプションバリュー(簡体字)': 'タイトル名(簡体字)',
94
+ 'オプションバリューリード文(日本語)': 'リード文(日本語)',
95
+ 'オプションバリューリード文(英語)': 'リード文(英語)',
96
+ 'オプションバリューリード文(韓国語)': 'リード文(韓国語)',
97
+ 'オプションバリューリード文(繁体字)': 'リード文(繁体字)',
98
+ 'オプションバリューリード文(簡体字)': 'リード文(簡体字)'
99
+ }
100
+ df = df.rename(columns=rename_map)
101
+ df = df.rename(columns=rename_map)
102
+ return df
103
+
104
+ def extract_unique_texts(df: pd.DataFrame, targets: List[str], which_column: str) -> List[str]:
105
+ """Extract all unique Japanese texts that need translation."""
106
+ unique_texts = set()
107
+
108
+ # Process both dataframes
109
+ for column in targets:
110
+ column_ja = column + "(日本語)"
111
+ if column_ja in df.columns:
112
+ # Add non-empty text values to the set
113
+ unique_texts.update([
114
+ text for text in df[column_ja].dropna().unique()
115
+ if isinstance(text, str) and text.strip()
116
+ ])
117
+
118
+ logger.info(f"extracted unique text for {which_column}")
119
+
120
+ return list(unique_texts)
121
+
122
+
123
+ def batch_translate_texts(texts: List[str], target_languages: Dict[str, str]) -> Dict[str, Dict[str, str]]:
124
+ if not texts:
125
+ return {}
126
+
127
+ translations = {}
128
+ batch_size = int(sys.argv[1]) # 1回のリクエストで翻訳する件数(多すぎるとエラーになる可能性)
129
+
130
+ for i in range(0, len(texts), batch_size):
131
+ batch = texts[i:i + batch_size]
132
+ logger.info(f"Translating batch {i+1} - {i+len(batch)} / {len(texts)} ...")
133
+
134
+ # , Korean, Traditional Chinese, and Simplified Chinese
135
+ system_message = """
136
+ You are a professional translator for food menus. Please translate the given Japanese texts to English. Format your response as a JSON object with each original Japanese text
137
+ as a key, and for each key provide an object with translations to all requested languages.
138
+
139
+ For single words or short phrases, capitalize the first letter in English translations.
140
+ Don't include quotation marks in your translations.
141
+ Provide exactly one translation per text and language.
142
+ """
143
+
144
+ user_message = f"""
145
+ Please translate the following Japanese texts to {', '.join(target_languages.values())}:
146
+
147
+ {json.dumps(batch, ensure_ascii=False, indent=2)}
148
+
149
+ Format your response as a valid JSON object with this structure:
150
+ {{
151
+ "Japanese text 1": {{
152
+ "English": "English translation",
153
+ }},
154
+ ...
155
+ }}
156
+ """
157
+ logger.info(f"prompt start:\n{user_message}\n:end")
158
+ # "Korean": "Korean translation",
159
+ # "Traditional Chinese": "Traditional Chinese translation",
160
+ # "Simplified Chinese": "Simplified Chinese translation"
161
+
162
+ try:
163
+ logger.info(f"Sending request for batch {i+1} - {i+len(batch)}...")
164
+
165
+ start_time = time.time() # 計測開始
166
+
167
+ response = openai.chat.completions.create(
168
+ model="gpt-4o-mini",
169
+ response_format={"type": "json_object"},
170
+ messages=[
171
+ {"role": "system", "content": system_message},
172
+ {"role": "user", "content": user_message}
173
+ ],
174
+ temperature=0.3,
175
+ )
176
+
177
+ end_time = time.time() # 計測終了
178
+ logger.info(f"Translation completed in {(end_time - start_time) // 60} minutes.")
179
+
180
+ response_content = response.choices[0].message.content
181
+ batch_translations = json.loads(response_content)
182
+
183
+ # ログファイルにリクエスト・レスポンスを保存(デバッグ用)
184
+ with open("translation_log.jsonl", "a", encoding="utf-8") as log_file:
185
+ log_file.write(json.dumps({
186
+ "batch_start": i+1,
187
+ "batch_end": i+len(batch),
188
+ "request": batch,
189
+ "response": batch_translations
190
+ }, ensure_ascii=False) + "\n")
191
+
192
+ # 結果を統合
193
+ translations.update(batch_translations)
194
+
195
+ except Exception as e:
196
+ logger.info(f"Error during translation batch {i+1} - {i+len(batch)}: {e}")
197
+ continue
198
+
199
+ logger.info("All translations completed.")
200
+ return translations
201
+
202
+
203
+ def update_dataframes_with_translations(
204
+ df: pd.DataFrame,
205
+ translations: Dict[str, Dict[str, str]],
206
+ target_columns: List[str],
207
+ languages: Dict[str, str],
208
+ which_column: str
209
+ ):
210
+ """Update the dataframes with the translations."""
211
+ if not translations:
212
+ logger.info("No translations to apply")
213
+ return
214
+
215
+ # Process both dataframes
216
+ for jp_column in target_columns:
217
+ jp_column_par = jp_column + "(日本語)"
218
+ if jp_column_par not in df.columns:
219
+ logger.info(f"jp {jp_column_par} not found in df columns")
220
+ continue
221
+
222
+ # Update each language column
223
+ for jp_lang, en_lang in languages.items():
224
+ target_column = f"{jp_column}({jp_lang})"
225
+
226
+ # Skip if target column doesn't exist
227
+ if target_column not in df.columns:
228
+ logger.info(f"target {target_column} not found in df columns")
229
+ continue
230
+
231
+ df[target_column] = df[target_column].astype(object)
232
+
233
+ # Apply translations
234
+ for i, value in enumerate(df[jp_column_par]):
235
+ if isinstance(value, str) and value.strip() and value in translations:
236
+ df.at[i, target_column] = translations[value].get(en_lang, "")
237
+
238
+ logger.info(f"Applied translations to dataframes for {which_column}")
239
+
240
+ def save_translations_to_json(translations: Dict[str, Dict[str, str]], filename: str = "translations.json"):
241
+ """Save translated contents in local PC as a json file"""
242
+ try:
243
+ with open(filename, "w", encoding="utf-8") as f:
244
+ json.dump(translations, f, ensure_ascii=False, indent=2)
245
+ logger.info(f"Translations saved to {filename}")
246
+ except Exception as e:
247
+ logger.info(f"Failed to save translations to JSON: {e}")
248
+
249
+
250
+ def save_to_excel(dishes_df: pd.DataFrame, options_df: pd.DataFrame):
251
+ """Save the updated dataframes back to Excel."""
252
+ try:
253
+ with pd.ExcelWriter(OUTPUT_FILE) as writer:
254
+ dishes_df.to_excel(writer, sheet_name="料理", index=False)
255
+ options_df.to_excel(writer, sheet_name="オプション", index=False)
256
+ logger.info(f"Successfully saved to {OUTPUT_FILE}")
257
+ except Exception as e:
258
+ logger.info(f"Error saving Excel file: {e}")
259
+
260
+ def save_to_excel_and_upload_to_s3(dishes_df, options_df, shop_id, bucket_name="operation-menu-boy"):
261
+ file_key = f"{shop_id}/翻訳結果/{shop_id}_translated.xlsx"
262
+ s3_manager = S3Manager(bucket_name)
263
+ s3_manager.upload_excel_to_s3(dishes_df, options_df, file_key)
264
+
265
+ def load_translations_from_json(filename: str) -> Dict[str, Dict[str, str]]:
266
+ try:
267
+ with open(filename, "r", encoding="utf-8") as f:
268
+ translations = json.load(f)
269
+ logger.info(f"Loaded translations from {filename}")
270
+ return translations
271
+ except Exception as e:
272
+ logger.info(f"Failed to load translations from JSON: {e}")
273
+ return {}
274
+
275
+ if __name__ == "__main__":
276
+ main()
translate_exe_old.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import os
3
+ from domain.translator import GeminiTranslator, OpenAITranslator
4
+ from services.translate_manager import DishTranslator
5
+ from config.variables import *
6
+ from logging import INFO, DEBUG
7
+ from services.s3_manager import S3Manager
8
+ logger.setLevel(INFO)
9
+ pd.set_option('display.max_columns', None)
10
+
11
+ from domain.dish import Dish
12
+ # spreadsheet_format_version = sys.argv[3]
13
+ # spreadsheet_format_version = "v1"
14
+ # dish_inst = Dish(spreadsheet_format_version)
15
+ # df = dish_inst.get_df(excel)
16
+ # df = dish_inst.get_df(excel).head(20)
17
+ df = pd.read_csv("/Users/keisukeogawa/Downloads/personal/AtoX/translate_tool_internal/before_translate2.csv")
18
+
19
+ # gemini_api_key = os.getenv("GEMINI_API_KEY")
20
+ # translator = GeminiTranslator(gemini_api_key)
21
+ openai_api_key = os.getenv("OPENAI_API_KEY")
22
+ translator = OpenAITranslator(openai_api_key)
23
+
24
+ # DishTranslatorのインスタンスを作成
25
+ df_translator = DishTranslator(df, translator)
26
+
27
+ # DataFrameの翻訳を実行
28
+ translated_df = df_translator.translate_columns()
29
+ translated_df.to_csv('translated_df.csv', index=False, encoding='utf-8-sig')
30
+ logger.info("exported translated_df.csv")
31
+ # logger.info(translated_df)
32
+
33
+ # CSVとしてS3に保存
34
+ bucket_name = "operation-menu-boy"
35
+ OUTPUT_FILE_KEY = f"{shop_id}/翻訳結果/{shop_id}_translated.csv"
36
+
37
+ s3_manager = S3Manager(bucket_name)
38
+ s3_manager.upload_df_to_s3(translated_df, OUTPUT_FILE_KEY)