Spaces:
Running
Running
import pandas as pd | |
import faiss | |
import numpy as np | |
from sklearn.feature_extraction.text import TfidfVectorizer | |
import openai | |
import re | |
# OpenAI APIキーの設定 | |
openai.api_key = 'sk-proj-DPOmB18OMmbaRqaJiwcyT3BlbkFJDFRur7edv66R8WEThq72' # ここにAPIキーを入力してください | |
# CSVファイルの作成 | |
data = [ | |
{"question_id": 1, "question_text": "1770年前後から1920年前後までの約150年間の時期に、ヨーロッパ、南北アメリカ、東アジアにおいて、諸国で政治のしくみがどのように変わったか、およびどのような政体の独立国が誕生したかを記述せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 2, "question_text": "のちの9世紀に活躍するようになったマムルークの特徴と、彼らがこの王朝で果たした役割とについて、2行以内で記せ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 3, "question_text": "クテシフォンを建設した国の名前に言及しつつ、その国で起こった文化的変容について、言語面を中心に、2行以内で記せ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 4, "question_text": "1世紀から4世紀末にかけてのローマ帝国におけるキリスト教と政治権力との関係の推移について、4行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 5, "question_text": "325年、キリスト教の教義形成にとって重要な会議が開催された。この会議について、その名称に触れながら3行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 6, "question_text": "セリム1世治下のオスマン帝国による対外戦争の成果について、2行以内で記せ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 7, "question_text": "書物に関して、清はどのような政策を展開したか。書物や編纂物の名称を挙げながら、3行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 8, "question_text": "最古の成文法の一つであるハンムラビ法典は、イスラーム法にも影響を与えたとされる。この法典が制定された時期と、その内容の特徴を、2行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 9, "question_text": "1979年のイラン革命では、イスラーム法に通じた宗教指導者(法学者)ホメイニらが中心となり、それまでのイランで推進されていた政策を批判した。このとき批判された政策について、2行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 10, "question_text": "大憲章(マグナ=カルタ)が作成された経緯を、課税をめぐる事柄を中心に、4行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 11, "question_text": "マキアヴェリが『君主論』で述べた主張について、2行以内で説明せよ。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 12, "question_text": "14世紀から15世紀にかけての西ヨーロッパでは、農民による反乱が起こる以前から、農民の地位は向上しはじめていた。その複数の要因を3行以内で説明しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 13, "question_text": "ロシアの農奴解放令によって農民の身分は自由になったが、農民の生活状況はあまり改善されなかった。それはなぜだったのかを3行以内で説明しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 14, "question_text": "1896年に起きたフィリピン革命によって、フィリピンの統治体制はどのように変化していくか。その歴史的過程を4行以内で説明しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 15, "question_text": "漢の武帝の時代、中国の北辺の支配をめぐり激しい攻防を繰り返した騎馬遊牧民国家の前3世紀末頃の状況について、2行以内で記しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 16, "question_text": "清末には、漢民族自立の気運がおこる一方で、清朝の下にあったモンゴルやチベットでも独立の気運が高まった。辛亥革命前後のモンゴルとチベットの独立の動きについて、3行以内で記しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 17, "question_text": "オーストラリアは、ヨーロッパから最も遠く離れた植民地の一つであった。現在では多民族主義・多文化主義の国であるが、1970年代までは白人中心主義がとられてきた。ヨーロッパ人の入植の経緯と白人中心主義が形成された過程とを、2行以内で記しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 18, "question_text": "第一次世界大戦後、1920年代のアメリカ合衆国では、移民や黒人に対する排斥運動が活発化した。これらの運動やそれに関わる政策の概要を、3行以内で記しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
{"question_id": 19, "question_text": "アメリカ合衆国は、戦争による領土の拡大や併合によっても多様な住民を抱えることになった。このうち、1846年に開始された戦争の名、およびその戦争の経緯について、2行以内で記しなさい。", "correct_answer": "The major causes of World War I were..."}, | |
] | |
# データフレームに変換 | |
df = pd.DataFrame(data) | |
# CSVファイルとして保存 | |
csv_file_path = "tokyo_univ_history_questions.csv" | |
df.to_csv(csv_file_path, index=False) | |
# データの読み込み | |
if not os.path.exists(csv_file_path): | |
raise FileNotFoundError(f"CSVファイルが見つかりません: {csv_file_path}") | |
data = pd.read_csv(csv_file_path) | |
# 列が存在するか確認 | |
required_columns = ["question_id", "question_text", "correct_answer"] | |
for col in required_columns: | |
if col not in data.columns: | |
raise ValueError(f"CSVファイルに'{col}'列が存在しません。") | |
vectorizer = TfidfVectorizer() | |
vectors = vectorizer.fit_transform(data["question_text"]).toarray() | |
index = faiss.IndexFlatL2(vectors.shape[1]) | |
index.add(vectors) | |
# 類似問題の生成関数 | |
def find_similar_question(question_text): | |
query_vector = vectorizer.transform([question_text]).toarray() | |
_, I = index.search(query_vector, 1) | |
similar_question = data.iloc[I[0][0]]["question_text"] | |
return similar_question | |
def generate_similar_question(): | |
random_index = np.random.choice(data.index) | |
base_question = data.loc[random_index, "question_text"] | |
similar_question = find_similar_question(base_question) | |
print(f"Base question: {base_question}") | |
print(f"Similar question: {similar_question}") | |
response = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=[ | |
{"role": "system", "content": "You are a helpful assistant."}, | |
{"role": "user", "content": f"Generate a new history question similar to: {similar_question}"} | |
], | |
max_tokens=1500 | |
) | |
new_question = response['choices'][0]['message']['content'].strip() | |
print(f"Generated question: {new_question}") | |
return new_question | |
# 新しい質問に対する正解を生成する関数 | |
def generate_correct_answer(new_question): | |
response = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=[ | |
{"role": "system", "content": "You are a helpful assistant."}, | |
{"role": "user", "content": f"Provide an ideal answer for the following question: {new_question}"} | |
], | |
max_tokens=1500 | |
) | |
correct_answer = response['choices'][0]['message']['content'].strip() | |
print(f"Generated correct answer: {correct_answer}") | |
return correct_answer | |
#問題を採点する関数 | |
def generate_and_evaluate(new_question, user_answer): | |
if not new_question: | |
return "Failed to generate a new question.", 0, "Failed to generate a new question." | |
response = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=[ | |
{"role": "system", "content": "You are an expert on world history."}, | |
{"role": "user", "content": f"Evaluate the following answer:\n\nQuestion: {new_question}\nAnswer: {user_answer}\n\nProvide a score between 0 and 100, taking into account partial correctness. Only return the numerical score."} | |
], | |
max_tokens=100 | |
) | |
response_text = response['choices'][0]['message']['content'].strip() | |
evaluation = float(re.search(r'\d+', response_text).group()) | |
if evaluation == 100: | |
feedback = "完璧です" | |
elif evaluation > 90: | |
feedback = "ほとんど完璧です" | |
elif evaluation > 70: | |
feedback = "正解に近いです" | |
elif evaluation > 50: | |
feedback = "良い答えです" | |
elif evaluation > 30: | |
feedback = "部分的には正しいです" | |
else: | |
feedback = "もう少し勉強しましょう" | |
return evaluation, feedback | |
# Gradioインターフェースの作成 | |
with gr.Blocks() as iface: | |
new_question = gr.State() | |
with gr.Row(): | |
generate_button = gr.Button("新しく出題") | |
with gr.Row(): | |
generated_question = gr.Textbox(label="問題", interactive=False) | |
with gr.Row(): | |
answer_input = gr.Textbox(label="回答") | |
with gr.Row(): | |
evaluate_button = gr.Button("採点") | |
with gr.Row(): | |
evaluation_output = gr.Number(label="得点", interactive=False) | |
feedback_output = gr.Textbox(label="フィードバック", interactive=False) | |
with gr.Row(): | |
correct_answer_button = gr.Button("正当例を見る") | |
with gr.Row(): | |
correct_answer_output = gr.Textbox(label="正当例", interactive=False) | |
def generate_question(): | |
question = generate_similar_question() | |
return question, question | |
def evaluate(question, answer): | |
score, feedback = generate_and_evaluate(question, answer) | |
return score, feedback | |
def get_correct_answer(question): | |
answer = generate_correct_answer(question) | |
return answer | |
generate_button.click(generate_question, inputs=[], outputs=[new_question, generated_question]) | |
evaluate_button.click(evaluate, inputs=[new_question, answer_input], outputs=[evaluation_output, feedback_output]) | |
correct_answer_button.click(get_correct_answer, inputs=new_question, outputs=correct_answer_output) | |
iface.launch() |