yosuke-i commited on
Commit
5b07cee
1 Parent(s): f6ebb2e

Upload 11 files

Browse files
Files changed (11) hide show
  1. README.md +4 -5
  2. app.py +182 -1
  3. category.py +31 -0
  4. chatgpt_api.py +35 -0
  5. convert_chukan_fmt_1.py +140 -0
  6. kousei.py +73 -0
  7. manuscript_conversion.py +68 -0
  8. openai.py +12 -0
  9. select_question.py +92 -0
  10. translate.py +30 -0
  11. voice_create.py +113 -0
README.md CHANGED
@@ -1,13 +1,12 @@
1
  ---
2
- title: English2
3
- emoji: 📈
4
  colorFrom: green
5
- colorTo: pink
6
  sdk: gradio
7
- sdk_version: 4.36.1
8
  app_file: app.py
9
  pinned: false
10
- license: apache-2.0
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: English
3
+ emoji: 🏢
4
  colorFrom: green
5
+ colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 4.27.0
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1 +1,182 @@
1
- ConnectionResetError
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import tempfile
4
+ import os
5
+ import re
6
+ from chatgpt_api import get_chatgpt_response
7
+ from voice_create import text_to_speech
8
+ from select_question import create_choice_question
9
+ from manuscript_conversion import manuscript_conversion
10
+ from category import check
11
+ from kousei import kousei2
12
+ from convert_chukan_fmt_1 import convert_chukan_fmt_1
13
+
14
+ def kousei(csv_file, input_text):
15
+ prompt_text = input_text + "指摘は、全ての問題において問題がない場合も含めて、必ず全問題、[id]に続けて結果を書くフォーマットで返してください。[id]の後は改行しないで。[id]はリクエストと完全一致の形式で。(必ず[問題ID]が5つ表示されるはずです)指摘方法は、問題ない場合は「問題なし」、指摘がある場合は「問題あり」\n「問題あり」の場合、問題のある箇所を具体的に指摘してください。\n#リスト"
16
+
17
+ # CSVファイルを読み込む
18
+ df = pd.read_csv(csv_file)
19
+ # 'id'列のデータ型を文字列に変換
20
+ df['id'] = df['id'].astype(str)
21
+ # DataFrameを5行ごとに処理するためのグループ化
22
+ df['group_id'] = df.index // 5
23
+ grouped = df.groupby('group_id')
24
+
25
+ # 各グループに対してフォーマットされたプロンプトを作成
26
+ def create_prompt(group, base_prompt):
27
+ prompt = base_prompt
28
+ for _, row in group.iterrows():
29
+ prompt += f"\n[{row['id']}]\n{row['原稿']}"
30
+ print(prompt)
31
+ return prompt
32
+
33
+ # 各グループごとのプロンプトを生成
34
+ prompts = grouped.apply(lambda g: create_prompt(g, prompt_text))
35
+ prompts = prompts.reset_index(name='prompt_after')
36
+
37
+ # 各プロンプトをAPIに送信(この部分は実装に応じて修正が必要です)
38
+ prompts['response'] = prompts['prompt_after'].apply(get_chatgpt_response)
39
+ print(prompts['response'])
40
+
41
+ # 各グループに対してフォーマットされたプロンプトを作成
42
+ def create_prompt(group, base_prompt):
43
+ prompt = base_prompt
44
+ for _, row in group.iterrows():
45
+ prompt += f"\n[{row['id']}]\n{row['原稿']}"
46
+ print(prompt)
47
+ return prompt
48
+
49
+ # 各グループごとのプロンプトを生成
50
+ prompts = grouped.apply(lambda g: create_prompt(g, prompt_text))
51
+ prompts = prompts.reset_index(name='prompt_after')
52
+
53
+ # 各プロンプトをAPIに送信(この部分は実装に応じて修正が必要です)
54
+ prompts['response'] = prompts['prompt_after'].apply(get_chatgpt_response)
55
+ print(prompts['response'])
56
+
57
+
58
+
59
+ # 応答を分割して元のDataFrameにマッピングする関数
60
+ def split_responses(grouped_df):
61
+ rows = []
62
+ for _, row in grouped_df.iterrows():
63
+ response = row['response']
64
+ split_response = re.split(r'\[([^\]]+)\]\s*', response)
65
+ ids_texts = list(zip(split_response[1::2], split_response[2::2]))
66
+
67
+ for id_text in ids_texts:
68
+ problem_id, correction_result = id_text
69
+ # フィルタリングされたDataFrameを安全に取得
70
+ filtered_df = df[df['id'] == problem_id]
71
+ original_content = filtered_df['原稿'].iloc[0] if not filtered_df.empty else "原稿が見つかりません"
72
+ rows.append({
73
+ 'id': problem_id,
74
+ 'contents': original_content,
75
+ '校正結果': correction_result.strip()
76
+ })
77
+
78
+ return pd.DataFrame(rows)
79
+
80
+ final_results = split_responses(prompts)
81
+
82
+ # ファイル出力
83
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
84
+ final_results.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
85
+ output_path = tmp.name
86
+
87
+ # ファイル名を変更
88
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
89
+ os.rename(output_path, new_path)
90
+ return new_path
91
+
92
+ title = "英語生成ツール"
93
+
94
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
95
+ gr.Markdown(
96
+ f"""
97
+ # {title}
98
+ """
99
+ )
100
+ with gr.Tab("問題生成(選択肢)"):
101
+ with gr.Column():
102
+ gr.Markdown("""
103
+ ## 利用手順
104
+ 1. こちらの[マスタ](https://drive.google.com/uc?export=download&id=1VyDBtVrnDUlddmITiXg7ybqyB0CTCPeu)を手元に置く
105
+ 2. シート「input」に、生成したい問題パターンを書いてください(赤字の要素は固定。選択肢は可変。適宜行追加OK)
106
+ 3. 完成したら、「ファイル>名前を付けて保存」から「CSV UTF-8(コンマ区切り)(*.csv)」形式で保存
107
+ 4. 3のCSVを本サイトにアップロード
108
+ """)
109
+
110
+ with gr.Row():
111
+ inputs=gr.File(label="CSVファイルをアップロード")
112
+ outputs=gr.File(label="ダウンロード", file_count="singular")
113
+ gr.Button("問題生成").click(
114
+ create_choice_question,
115
+ inputs=[inputs],
116
+ outputs=[outputs]
117
+ )
118
+ with gr.Tab("原稿変換"):
119
+ with gr.Column():
120
+ with gr.Row():
121
+ inputs=gr.File(label="CSVファイルをアップロード")
122
+ outputs=gr.File(label="ダウンロード", file_count="singular")
123
+ gr.Button("変換").click(
124
+ manuscript_conversion,
125
+ inputs=[inputs],
126
+ outputs=[outputs]
127
+ )
128
+ with gr.Tab("校正"):
129
+ with gr.Column():
130
+ input_text_kousei = gr.Textbox(label="校正観点を入力してください。",value="英単語習得を目的として、以下2種類の問題を用意しています。\n1.英語の正しい日本語訳を選択する4択問題\n2.日本語の正しい英語訳を選択する4択問題\n「#リスト」の誤答選択肢の中に、正解選択肢の別解になってしまっているもの、または別解とは言えないが紛らわしすぎるものがないか、探して指摘してください。")
131
+ with gr.Row():
132
+ inputs=gr.File(label="CSVファイルをアップロード")
133
+ outputs=gr.File(label="ダウンロード", file_count="singular")
134
+ gr.Button("校正スタート").click(
135
+ kousei,
136
+ inputs=[inputs,input_text_kousei],
137
+ outputs=[outputs]
138
+ )
139
+ with gr.Tab("校正2"):
140
+ with gr.Column():
141
+ radio_options = ["英語", "日本語"]
142
+ radio_button = gr.Radio(choices=radio_options, label="選択してください",value="英語")
143
+ input_text_kousei = gr.Textbox(label="校正観点を入力してください。",value="If there are any typographical errors, omissions, missing or extra spaces and periods, or grammatical mistakes in the English text, please point them out.")
144
+ with gr.Row():
145
+ inputs=gr.File(label="CSVファイルをアップロード")
146
+ outputs=gr.File(label="ダウンロード", file_count="singular")
147
+ gr.Button("校正スタート").click(
148
+ kousei2,
149
+ inputs=[inputs,input_text_kousei,radio_button],
150
+ outputs=[outputs]
151
+ )
152
+ with gr.Tab("音声生成"):
153
+ with gr.Column():
154
+ # GradioのUIコンポーネントを定義
155
+ radio_options = ["ブレイクタイム有", "ブレイクタイム無"]
156
+ radio_button = gr.Radio(choices=radio_options, label="選択してください",value="ブレイクタイム有")
157
+ with gr.Row():
158
+ file_input = gr.File(label="CSVファイルをアップロード")
159
+ submit_button = gr.Button("音声ファイルを生成")
160
+ file_output = gr.File(label="ダウンロード")
161
+ submit_button.click(fn=text_to_speech, inputs=[file_input,radio_button], outputs=[file_output])
162
+ with gr.Tab("中間マスタ生成(意味理解)"):
163
+ with gr.Column():
164
+ with gr.Row():
165
+ file_input = gr.File(label="CSVアップロード")
166
+ submit_button = gr.Button("ファイルコンバート")
167
+ file_output = gr.File(label="ファイルをダウンロード")
168
+ submit_button.click(fn=convert_chukan_fmt_1, inputs=[file_input], outputs=[file_output])
169
+ with gr.Tab("カテゴリ分類"):
170
+ with gr.Column():
171
+ input_text_kousei = gr.Textbox(label="分類観点を入力してください。",value="xxxxxxxに関する内容の場合は「該当あり」と書いてください。")
172
+ with gr.Row():
173
+ inputs=gr.File(label="CSVファイルをアップロード")
174
+ outputs=gr.File(label="ダウンロード", file_count="singular")
175
+ gr.Button("分類スタート").click(
176
+ check,
177
+ inputs=[inputs,input_text_kousei],
178
+ outputs=[outputs]
179
+ )
180
+
181
+ demo.launch(share=True)
182
+
category.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import tempfile
4
+ import os
5
+ from chatgpt_api import get_chatgpt_response2
6
+ from voice_create import text_to_speech
7
+ from select_question import create_choice_question
8
+ from manuscript_conversion import manuscript_conversion
9
+
10
+
11
+ def check(csv_file, input_text):
12
+ prompt_text = input_text + "該当しない場合は「該当なし」、該当する場合は「該当あり」としてください\n"
13
+ # CSVファイルを読み込む
14
+ df = pd.read_csv(csv_file)
15
+ # 'id'列のデータ型を文字列に変換
16
+ df['id'] = df['id'].astype(str)
17
+
18
+ df["prompt"] = prompt_text + df["原稿"]
19
+
20
+ df["分類結果"] = df["prompt"].apply(get_chatgpt_response2)
21
+
22
+
23
+ # ファイル出力
24
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
25
+ df.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
26
+ output_path = tmp.name
27
+
28
+ # ファイル名を変更
29
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
30
+ os.rename(output_path, new_path)
31
+ return new_path
chatgpt_api.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+
4
+ # OpenAI API キーを設定する
5
+ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "sk-proj-arrJA9XvKeo5nfYXLgmeT3BlbkFJNnqFQL9G8qTdYXsBvhJc")
6
+
7
+ def get_chatgpt_response(input_text):
8
+ headers = {
9
+ "Content-Type": "application/json",
10
+ "Authorization": f"Bearer {OPENAI_API_KEY}"
11
+ }
12
+ data = {
13
+ "model": "gpt-4o",
14
+ "messages": [{"role": "user", "content": input_text}]
15
+ }
16
+ response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=data)
17
+ response_json = response.json()
18
+ output_text = response_json["choices"][0]["message"]["content"]
19
+
20
+ return output_text
21
+
22
+ def get_chatgpt_response2(input_text):
23
+ headers = {
24
+ "Content-Type": "application/json",
25
+ "Authorization": f"Bearer {OPENAI_API_KEY}"
26
+ }
27
+ data = {
28
+ "model": "gpt-4o",
29
+ "messages": [{"role": "user", "content": input_text}]
30
+ }
31
+ response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=data)
32
+ response_json = response.json()
33
+ output_text = response_json["choices"][0]["message"]["content"]
34
+
35
+ return output_text
convert_chukan_fmt_1.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import os
3
+ import tempfile
4
+ import re
5
+ import random
6
+ import gradio as gr
7
+
8
+
9
+ # id作成
10
+ def make_id(stage, order):
11
+ """
12
+ 指定された stage と order に基づいてIDを生成します。
13
+
14
+ Parameters:
15
+ stage (int): ステージ番号
16
+ order (int): オーダー番号
17
+
18
+ Returns:
19
+ str: 特定のフォーマットのID文字列
20
+ """
21
+ # フォーマットに従ってIDを生成
22
+ id_str = f"EC03ST{stage:03d}L{order:03d}"
23
+ return id_str
24
+
25
+ def extract_correct_choice(text):
26
+ # Use a regular expression to find the content after "【正解選択肢】"
27
+ match = re.search(r'【正解選択肢】(.+)', text)
28
+ if match:
29
+ return match.group(1).strip()
30
+ else:
31
+ return None
32
+
33
+ # 選択肢シャッフルの関数
34
+ def shuffle_and_combine_options(text_a, text_b):
35
+ # 正規表現を使って各選択肢を抽出し、タグを除去する
36
+ def extract_and_clean_options(text):
37
+ matches = re.findall(r'【[^】]+】([^【]+)', text)
38
+ return [match.strip() for match in matches]
39
+
40
+ # 列Aと列Bの選択肢を抽出してクリーンアップ
41
+ options_a = extract_and_clean_options(text_a)
42
+ options_b = extract_and_clean_options(text_b)
43
+
44
+ # シャッフルのためのインデックスリストを作成
45
+ indices = list(range(len(options_a)))
46
+ random.shuffle(indices)
47
+
48
+ # シャッフルされた選択肢を作成
49
+ shuffled_a = [options_a[i] for i in indices]
50
+ shuffled_b = [options_b[i] for i in indices]
51
+
52
+ # 各選択肢を/で区切って結合
53
+ result_a = "/".join(shuffled_a)
54
+ result_b = "/".join(shuffled_b)
55
+
56
+ return result_a, result_b
57
+
58
+ # 解説作成
59
+ def create_explanation(script_english,script_japanese,choices_english, choices_japanese,question_english,question_japanese):
60
+ choices_english = choices_english.replace("/", "\n")
61
+ choices_japanese = choices_japanese.replace("/", "\n")
62
+ question_english = "" if question_english == "" or pd.isnull(question_english) else "\n\nQuestion:\n" + question_english
63
+ question_japanese = "" if question_japanese == "" or pd.isnull(question_japanese) else "\n\nQuestion:\n" + question_japanese
64
+ explanation = f"■英語\n{script_english}{question_english}\n\n選択肢:\n{choices_english}\n\n■日本語訳\n{script_japanese}{question_japanese}\n\n選択肢:\n{choices_japanese}"
65
+ return explanation
66
+
67
+
68
+ def convert_chukan_fmt_1(csv_file):
69
+ df_input = pd.read_csv(csv_file.name)
70
+ data = {
71
+ "問題ID": [],
72
+ "知識ID":[],
73
+ "出題形式ID":[],
74
+ "リード文":[],
75
+ "問題":[],
76
+ "問題_翻訳":[],
77
+ "正解文":[],
78
+ "解説テキスト":[],
79
+ "選択肢":[],
80
+ "正解":[],
81
+ "script":[],
82
+ "question":[],
83
+ "choices":[],
84
+ "eikenn":[],
85
+ }
86
+ for index, row in df_input.iterrows():
87
+ id = make_id(row["ステージ"], row["ステージ内表示順"])
88
+ try:
89
+ japanese_selection_1, english_selection_1 = shuffle_and_combine_options(row["日本語訳_問題1_選択肢"], row["問題1_選択肢"])
90
+ print(id)
91
+ data["問題ID"].append(id+"Q001")
92
+ data["知識ID"].append(id)
93
+ data["出題形式ID"].append(row["出題形式ID"])
94
+ data["リード文"].append(row["リード文"])
95
+ data["問題"].append("")
96
+ data["問題_翻訳"].append(extract_correct_choice(row["日本語訳_問題1_選択肢"]))
97
+ data["正解文"].append(extract_correct_choice(row["問題1_選択肢"]))
98
+ data["解説テキスト"].append(create_explanation(row["問題1_スクリプト"], row["日本語訳_問題1_スクリプト"], english_selection_1, japanese_selection_1, row["問題1_Question"], row["日本語訳_問題1_Question"]))
99
+ data["選択肢"].append(english_selection_1)
100
+ data["正解"].append(extract_correct_choice(row["問題1_選択肢"]))
101
+ data["script"].append(row["問題1_スクリプト"])
102
+ data["question"].append(row["問題1_Question"])
103
+ data["choices"].append(english_selection_1 if row["選択肢読み上げ有無"] == "有" else "")
104
+ data["eikenn"].append(row["レベル"])
105
+
106
+ japanese_selection_2, english_selection_2 = shuffle_and_combine_options(row["日本語訳_問題2_選択肢"], row["問題2_選択肢"])
107
+ id = make_id(row["ステージ"], row["ステージ内表示順"])
108
+ data["問題ID"].append(id+"Q002")
109
+ data["知識ID"].append(id)
110
+ data["出題形式ID"].append(row["出題形式ID"])
111
+ data["リード文"].append(row["リード文"])
112
+ data["問題"].append("")
113
+ data["問題_翻訳"].append(extract_correct_choice(row["日本語訳_問題2_選択肢"]))
114
+ data["正解文"].append(extract_correct_choice(row["問題2_選択肢"]))
115
+ data["解説テキス���"].append(create_explanation(row["問題2_スクリプト"], row["日本語訳_問題2_スクリプト"], english_selection_2, japanese_selection_2, row["問題2_Question"], row["日本語訳_問題2_Question"]))
116
+ data["選択肢"].append(english_selection_2)
117
+ data["正解"].append(extract_correct_choice(row["問題2_選択肢"]))
118
+ data["script"].append(row["問題2_スクリプト"])
119
+ data["question"].append(row["問題2_Question"])
120
+ data["choices"].append(english_selection_2 if row["選択肢読み上げ有無"] == "有" else "")
121
+ data["eikenn"].append(row["レベル"])
122
+
123
+ except Exception as e:
124
+ gr.Warning(f"次の問題でエラーが発生: {id} - {str(e)}")
125
+ return f"次の問題でエラーが発生: {id} - {str(e)}"
126
+
127
+
128
+
129
+
130
+
131
+ df_output = pd.DataFrame(data)
132
+
133
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
134
+ df_output.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
135
+ output_path = tmp.name
136
+
137
+ # ファイル名を変更
138
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
139
+ os.rename(output_path, new_path)
140
+ return new_path
kousei.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import tempfile
4
+ import os
5
+ import re
6
+ from chatgpt_api import get_chatgpt_response2
7
+ from voice_create import text_to_speech
8
+ from select_question import create_choice_question
9
+ from manuscript_conversion import manuscript_conversion
10
+
11
+ def check_text(text, radio_option):
12
+ errors = []
13
+ error_details = []
14
+
15
+ # Split the text into sentences for individual checks
16
+ # This regex splits on punctuation but keeps the punctuation with the previous sentence
17
+ sentences = re.split(r'(?<=[。!??!.])\s*|\n', text)
18
+
19
+ for sentence in sentences:
20
+ sentence = sentence.strip()
21
+ if not sentence:
22
+ continue
23
+
24
+ if radio_option == "日本語":
25
+ if not re.search(r'[。!]$', sentence):
26
+ errors.append("文末に句点がありません。")
27
+ error_details.append(f"文末に「。」または「!」がない: '{sentence}'")
28
+ else:
29
+ # Check for multiple spaces
30
+ if re.search(r' +', sentence):
31
+ errors.append("半角スペースが2つ以上入っています。")
32
+ multiple_spaces_parts = re.findall(r'[^ ]* +[^ ]*', sentence)
33
+ for part in multiple_spaces_parts:
34
+ error_details.append(f"スペースが2つある部分: '{part.strip()}'")
35
+
36
+ # Check for punctuation at the end of the sentence
37
+ if not re.search(r'[.!?]$', sentence):
38
+ errors.append("文末にピリオドや?や!のいずれかがついていません。")
39
+ error_details.append(f"文末に「.」または「!」または「?」がない: '{sentence}'")
40
+
41
+ if errors:
42
+ return "チェック観点:\n" + "\n".join(errors) + "\n\n詳細:\n" + "\n".join(error_details)
43
+ else:
44
+ return "全てのチェックをクリアしました。"
45
+
46
+
47
+
48
+
49
+
50
+ def kousei2(csv_file, input_text,radio_option):
51
+ prompt_text = "#Instructions\n" + input_text +" If there is no problem, please reply with only 2 letters 'OK' and DON'T put any other extra words. \n #Target sentence\n"
52
+ # CSVファイルを読み込む
53
+ df = pd.read_csv(csv_file)
54
+ # 'id'列のデータ型を文字列に変換
55
+ df['id'] = df['id'].astype(str)
56
+
57
+ df["prompt"] = prompt_text + df["原稿"]
58
+
59
+ df["GPT校正結果"] = df["prompt"].apply(get_chatgpt_response2)
60
+ print("radio_option",radio_option)
61
+ df["タイプミス校正結果"] = df["原稿"].apply(check_text, args=(radio_option,))
62
+
63
+
64
+
65
+ # ファイル出力
66
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
67
+ df.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
68
+ output_path = tmp.name
69
+
70
+ # ファイル名を変更
71
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
72
+ os.rename(output_path, new_path)
73
+ return new_path
manuscript_conversion.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import re
3
+ import os
4
+ import tempfile
5
+
6
+
7
+ # 新しいカラムを作成する関数
8
+ def process_text(row, column_name):
9
+ script_start_pattern = r"##\s*リスニングスクリプト"
10
+ question_start = "Question:"
11
+ choice_start = "##選択肢"
12
+ correct_choice = "【正解選択肢】"
13
+
14
+ # 【正解選択肢】の直前に ##選択肢 を挿入する処理
15
+ if correct_choice in row[column_name] and not choice_start in row[column_name]:
16
+ row[column_name] = row[column_name].replace(correct_choice, choice_start + correct_choice)
17
+
18
+ # 正規表現を使用してスクリプト開始部分を探す
19
+ script_parts = re.split(script_start_pattern, row[column_name], flags=re.IGNORECASE)
20
+ if len(script_parts) > 1:
21
+ script_part = script_parts[1]
22
+ if choice_start in script_part:
23
+ choice_part = script_part.split(choice_start, 1)[1]
24
+ script_text = script_part.split(choice_start)[0].strip()
25
+ choice_text = choice_part.strip()
26
+
27
+ if question_start in script_text:
28
+ question_text = script_text.split(question_start, 1)[1]
29
+ script_text = script_text.split(question_start)[0].strip()
30
+ else:
31
+ question_text = ""
32
+
33
+ return pd.Series({
34
+ f'{column_name}_スクリプト': script_text,
35
+ f'{column_name}_Question': question_text,
36
+ f'{column_name}_選択肢': choice_text
37
+ })
38
+ # 必要なセクションが存在しない場合、空の文字列を返す
39
+ return pd.Series({
40
+ f'{column_name}_スクリプト': "",
41
+ f'{column_name}_Question': "",
42
+ f'{column_name}_選択肢': ""
43
+ })
44
+
45
+ # 処理を行うカラムのリスト
46
+ columns_to_process = ['問題1', '問題2', '日本語訳_問題1', '日本語訳_問題2']
47
+
48
+
49
+ def manuscript_conversion(csv_file):
50
+ # CSVファイルを読み込む
51
+ df = pd.read_csv(csv_file.name)
52
+
53
+ # 各カラムに対して処理を適用し、新しいカラムをDataFrameに追加
54
+ for column in columns_to_process:
55
+ df = df.join(df.apply(lambda row: process_text(row, column), axis=1))
56
+
57
+ # 元の問題1と問題2、日本語訳_問題1と日本語訳_問題2のカラムを削除
58
+ df.drop(columns=columns_to_process, inplace=True)
59
+
60
+ # csvを書き出す
61
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
62
+ # cp932で保存、エラーは無視(置換しても良い)
63
+ df.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
64
+ output_path = tmp.name
65
+ # ファイル名を変更
66
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
67
+ os.rename(output_path, new_path)
68
+ return new_path
openai.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # from openai import OpenAI
2
+ # client = OpenAI()
3
+
4
+ # def exec_gpt4(prompt):
5
+ # openai.api_key = 'sk-proj-arrJA9XvKeo5nfYXLgmeT3BlbkFJNnqFQL9G8qTdYXsBvhJc'
6
+ # response = client.chat.completions.create(
7
+ # model='gpt-4o',
8
+ # messages=[
9
+ # {"role": "user", "content": prompt},
10
+ # ],
11
+ # )
12
+ # return response.choices[0].message.content.strip()
select_question.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from chatgpt_api import get_chatgpt_response
2
+ import pandas as pd
3
+ import re
4
+ import tempfile
5
+ import os
6
+ from translate import translate_text
7
+
8
+
9
+ # プロンプトを作成
10
+ def make_prompt(df):
11
+ rows = []
12
+ for index, row in df.iterrows():
13
+ theme_str = str(row["テーマ"])
14
+ if theme_str.lower() == 'nan':
15
+ continue
16
+ themes_list = theme_str.split(',')
17
+
18
+ questiontext = ""
19
+ if "Question" in row["サンプル"]:
20
+ questiontext = "・Questionがある場合は、「##リスニングスクリプト」の表現を真似しすぎず、what,why,how,when,whereなど、多様な角度から問う\n"
21
+ else:
22
+ questiontext = ""
23
+
24
+ for theme in themes_list:
25
+ new_prompt = "#条件\n"+ "・以下の「#サンプル」の形式([問題1]##リスニングスクリプト ... ##選択肢...[問題2]##リスニングスクリプト...##選択肢...)で、"+row['レベル']+"レベルのリスニング問題を生成\n"+"・[問題1]から[問題"+str(int(row["問題数"]))+"]まで必ず##リスニングスクリプトを"+str(int(row["問題数"]))+"種類作成\n"+ "・「##リスニングスクリプト」から「##選択肢」まですべて出力\n"+ "・「##リスニングスクリプト」は"+row['スクリプトパターン']+"\n"+"・問題の難易度、word数は「##リスニングスクリプト」と同等レベル\n"+ questiontext +"・各問題は、[問題1][問題2]という形式で始める\n"+"・ただし、スクリプトの内容は、"+theme+"に関するスクリプト\n"+"・[問題1]から[問題"+str(int(row["問題数"]))+"]までの誤答選択肢はすべて異なる内容・異なるパターン \n \n"+"#サンプル\n"+row["サンプル"]
26
+ print(new_prompt)
27
+ rows.append({
28
+ "形式":row["形式2"],
29
+ "レベル":row["レベル"],
30
+ "テーマ":theme,
31
+ "選択肢読み上げ有無":row["選択肢読み上げ有無"],
32
+ "複製パターン":row["複製パターン"],
33
+ "プロンプト":new_prompt
34
+ })
35
+ result_df = pd.DataFrame(rows)
36
+ return result_df
37
+
38
+ # 問題の分割と展開
39
+ def expand_problems(df):
40
+ temp_data = []
41
+ # テキスト全体を処理
42
+ for index, row in df.iterrows():
43
+ print("返却値",row['問題1'])
44
+ # 正規表現を用いて各問題を分割
45
+ problems = re.findall(r'\[(問題\d+)\](.*?)(?=\[問題\d+\]|$)', row['問題1'], re.DOTALL)
46
+
47
+ # 各問題のIDとともに新たな行を追加
48
+ for num, text in problems:
49
+ temp_data.append({
50
+ "形式": row["形式"],
51
+ "レベル": row["レベル"],
52
+ "テーマ":row["テーマ"],
53
+ "選択肢読み上げ有無": row["選択肢読み上げ有無"],
54
+ "複製パターン": row["複製パターン"],
55
+ "問題1": text.strip()
56
+ })
57
+
58
+ # 一時リストから新しいDataFrameを作成
59
+ return pd.DataFrame(temp_data)
60
+
61
+ def create_choice_question(csv_file):
62
+ # CSVファイルを読み込む
63
+ df = pd.read_csv(csv_file.name)
64
+
65
+ # プロンプトを作成する
66
+ df_prompt = make_prompt(df)
67
+
68
+ # 問題を生成する
69
+ ## 問題1を生成する
70
+ df_prompt["問題1"] = df_prompt["プロンプト"].apply(get_chatgpt_response)
71
+
72
+ ## 問題1を展開する
73
+ result_df = expand_problems(df_prompt)
74
+
75
+ ## 問題2を生成する
76
+ result_df["プロンプト2"] = result_df["複製パターン"]+"\n"+result_df["問題1"]
77
+ result_df["問題2"] = result_df["プロンプト2"].apply(get_chatgpt_response)
78
+
79
+ # 翻訳する
80
+ result_df["翻訳_問題1"] = result_df["問題1"].apply(translate_text)
81
+ result_df["翻訳_問題2"] = result_df["問題2"].apply(translate_text)
82
+
83
+
84
+ # csvを書き出す
85
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as tmp:
86
+ # cp932で保存、エラーは無視(置換しても良い)
87
+ result_df.to_csv(tmp.name, index=False, encoding='cp932', errors='ignore')
88
+ output_path = tmp.name
89
+ # ファイル名を変更
90
+ new_path = os.path.join(os.path.dirname(output_path), "output.csv")
91
+ os.rename(output_path, new_path)
92
+ return new_path
translate.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+
4
+ def translate_text(text, target_lang='ja', source_lang='en'):
5
+ api_key = "AIzaSyAEzK5_n6zKTimD9yoXS-C8O0xN_4LaVBQ"
6
+ # 元の改行を `<br>` で置き換え
7
+ text = text.replace('\n', '<br>')
8
+ url = f"https://translation.googleapis.com/language/translate/v2?key={api_key}"
9
+ payload = {
10
+ 'q': text,
11
+ 'source': source_lang,
12
+ 'target': target_lang,
13
+ 'format': 'html' # フォーマットを 'html' に変更
14
+ }
15
+ headers = {
16
+ 'Content-Type': 'application/json'
17
+ }
18
+
19
+ response = requests.post(url, headers=headers, json=payload)
20
+ if response.status_code == 200:
21
+ translated_text = json.loads(response.text)['data']['translations'][0]['translatedText']
22
+ # 翻訳されたテキストの `<br>` を改行に戻す
23
+ translated_text = translated_text.replace('<br>', '\n')
24
+
25
+ # "##選択肢" と "【正解選択肢】" の間に改行を確実に挿入
26
+ translated_text = translated_text.replace("##選択肢【正解選択肢】", "##選択肢\n【正解選択肢】")
27
+
28
+ return translated_text
29
+ else:
30
+ return "Error: " + response.text
voice_create.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import zipfile
3
+ import base64
4
+ import os
5
+ import requests
6
+ import re
7
+
8
+ def remove_quotes(text):
9
+ # ダブルクォートを空文字に置き換える
10
+ return text.replace('"', '')
11
+
12
+ def text_to_speech(input_file,selected_option):
13
+ # APIキーを直接コードに埋め込む(実際の運用では推奨されません)
14
+ api_key = 'AIzaSyAEzK5_n6zKTimD9yoXS-C8O0xN_4LaVBQ' # ここを実際のAPIキーに置き換えてください
15
+ data = pd.read_csv(input_file)
16
+ zip_path = 'output_audio_files.zip'
17
+
18
+ with zipfile.ZipFile(zip_path, 'w') as z:
19
+ for idx, row in data.iterrows():
20
+ # script列が文字列か確認し、文字列でない場合は空文字に置き換える
21
+ script = row.get('script', '')
22
+ if not isinstance(script, str):
23
+ script = str(script)
24
+
25
+ # テキストをA:やB:で分割
26
+ parts = re.split(r'(A:|B:)', script)
27
+ print(parts)
28
+ ssml_parts = []
29
+ print(parts)
30
+ # 交互に発言するAとBの内容を順に処理
31
+ for i in range(1, len(parts), 2):
32
+ if parts[i] == "A:":
33
+ voice_name = row["voiceA"]
34
+ print("A")
35
+ elif parts[i] == "B:":
36
+ voice_name = row["voiceB"]
37
+ else:
38
+ print("空白")
39
+ continue # A:またはB:で始まらない行は無視
40
+
41
+ text = parts[i + 1].strip()
42
+ text = remove_quotes(text)
43
+ print("テキスト",text)
44
+
45
+
46
+ # 1sに変換する前に除外するコード
47
+ text = text.replace("a.m.", 'AM')
48
+ text = text.replace("p.m.", 'PM')
49
+ text = text.replace("U.S.", 'US')
50
+ text = text.replace("U.K.", 'UK')
51
+ text = text.replace("Mr.", 'Mister')
52
+ text = text.replace("Ms.", 'MIZ')
53
+ text = text.replace("Mrs.", 'Misiz')
54
+ text = text.replace("Dr.", 'Doctor')
55
+ text = text.replace("Mt.", 'Mount')
56
+
57
+
58
+ # テキスト内の改行を1sの間に変換
59
+ text = text.replace("\n", '<break time="1s"/>')
60
+ text = text.replace(".", '.<break time="500ms"/>')
61
+
62
+ if selected_option == "ブレイクタイム有":
63
+ # 「,」で時間を空ける
64
+ if row["eikenn"] in ["5級","4級","3級","準2級","2級","準1級"]:
65
+ text = text.replace(",", '<break time="50ms"/>')
66
+ print("タグ処理")
67
+ else:
68
+ pass
69
+
70
+ ssml_parts.append(f'<voice name="{voice_name}"><prosody rate="{row["speed"]}"><p>{text}</p></prosody></voice>')
71
+ print(ssml_parts)
72
+ ssml = '<speak>' + ''.join(ssml_parts)
73
+ print(ssml)
74
+
75
+ if pd.notna(row.get('question')) and row['question'] != '':
76
+ ssml += f'<break time="1s"/><voice name="{row["voiceQuestion"]}"><prosody rate="{row["speed"]}"><p>Question</p><break time="1s"/><p>{row["question"]}</p></prosody></voice>'
77
+ # Choices部分の追加
78
+ if pd.notna(row.get('choices')) and row['choices'] != '':
79
+ choices_list = row['choices'].split('/')
80
+ choices_ssml = '<break time="1s"/>'.join(choices_list)
81
+ ssml += f'<break time="1s"/><voice name="{row["voiceB"]}"><prosody rate="{row["speed"]}"><p>{choices_ssml}</p></prosody></voice>'
82
+ ssml += '</speak>'
83
+
84
+ print(ssml)
85
+ # APIリクエスト用のボディ
86
+ body = {
87
+ "input": {"ssml": ssml},
88
+ "voice": {"languageCode": "en-US"}, # 基本的な言語設定(必要に応じて行ごとに変更可能)
89
+ "audioConfig": {"audioEncoding": "MP3"}
90
+ }
91
+ headers = {
92
+ "X-Goog-Api-Key": api_key,
93
+ "Content-Type": "application/json"
94
+ }
95
+ url = "https://texttospeech.googleapis.com/v1/text:synthesize"
96
+ response = requests.post(url, headers=headers, json=body)
97
+ print("レスポンス",response)
98
+ response_data = response.json()
99
+ print("レスポンスデータ",response_data)
100
+
101
+ # 音声コンテンツの取得とファイル保存
102
+ if 'audioContent' in response_data:
103
+ audio_content = base64.b64decode(response_data['audioContent'])
104
+ file_name = f"{row['id']}.mp3"
105
+ with open(file_name, "wb") as out:
106
+ out.write(audio_content)
107
+
108
+ z.write(file_name)
109
+ os.remove(file_name)
110
+ else:
111
+ print("ファイル不備")
112
+
113
+ return zip_path