import streamlit as st import requests import os from dotenv import load_dotenv from gptcache import cache from gptcache.adapter import openai model = "gpt-4" constraints_filename = "constraints.md" template_filename = "template.md" load_dotenv() stored_api_key = os.getenv("OPENAI_API_KEY") stored_password = os.getenv("PASSWORD") openai_api_key = None # GPT Cache cache.init() cache.set_openai_key() def get_filetext(filename, filecache={}): if filename not in filecache: if not os.path.exists(filename): raise ValueError(f"ファイル '{filename}' が見つかりませんでした") with open(filename, "r") as f: filecache[filename] = f.read() return filecache[filename] def validate_api_key(api_key): try: response = requests.get( "https://api.openai.com/v1/models", headers={"Authorization": f"Bearer {api_key}"} ) response.raise_for_status() return True except requests.exceptions.HTTPError: return False def generate_question(): constraints = get_filetext(filename=constraints_filename) data = { "model": model, "messages": [ {"role": "system", "content": constraints}, {"role": "user", "content": "出題してください。"}, ], "max_tokens": 1024, "n": 1, "stop": None, "temperature": 0.7, } response = requests.post( "https://api.openai.com/v1/chat/completions", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {openai_api_key}" }, json=data ) response.raise_for_status() choice = response.json()['choices'][0] question = choice['message']['content'].strip() return question def check_answer(question, answer): template = get_filetext(filename=template_filename) data = { "model": model, "messages": [ {"role": "system", "content": template}, {"role": "user", "content": f"問題: {question}\n回答: {answer}"}, ], "max_tokens": 1024, "n": 1, "stop": None, "temperature": 0.7, } response = requests.post( "https://api.openai.com/v1/chat/completions", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {openai_api_key}" }, json=data ) response.raise_for_status() choice = response.json()['choices'][0] evaluation = choice['message']['content'].strip() return evaluation st.title("受験勉強支援AI") # パスワード認証、もしくは、ユーザーのAPIキーの入力でシステム利用を解放する if stored_api_key: password_or_api_key = st.text_input("パスワードまたはOpenAIのAPIキーを入力してください:") if password_or_api_key: if password_or_api_key == stored_password: openai_api_key = stored_api_key elif validate_api_key(password_or_api_key): openai_api_key = password_or_api_key else: st.write("無効なパスワードまたはAPIキーです。再度お試しください。") else: st.write("APIキーが設定されていません。設定を確認してください。") # 以下、主処理 if openai_api_key: question = st.session_state.get("question", None) if st.button("出題"): question = generate_question() st.session_state.question = question st.session_state.answer = "" st.experimental_rerun() if question: st.write("問題:") st.write(question) if "answer" not in st.session_state: st.session_state.answer = "" answer = st.text_area("回答を入力してください:", value=st.session_state.answer, key="answer_field") if st.button("添削"): evaluation = check_answer(question, answer) st.write("添削結果:") st.write(evaluation) st.session_state.answer = answer st.markdown( """

注意事項

  1. 回答前に問題の内容をよく確認してください。
  2. もし自身でこのスペースをコピーし、新たなサービスを自分で使う場合は、OpenAIのAPIキーとパスワードをシステム設定に設定しパスワード認証にすることができます。詳しくはosenv_setting_tips.txtを参照ください。
  3. 一方、第三者に、第三者のAPIキーで利用してもらいたい場合は、APIキーの認証で当サービスの利用を促すことも可能です。
  4. constraints.mdを修正すると、生成される問題の内容、雰囲気をカスタマイズすることが可能です。
  5. 当サービスでは、2023/3/1にリリースされたOpenAI社のChatGPT APIのgpt-3.5-turboを使用しております。
  6. 当サービスで生成された問題や添削結果は、OpenAI が提供する人工知能によるものであり、当サービスやOpenAI がその正確性や信頼性を保証するものではありません。
  7. OpenAI の利用規約に従い、データ保持しない方針です(ただし諸般の事情によっては変更する可能性はございます)。
  8. 当サービスで生成された問題や添削結果は事実確認をした上で、ユーザーの責任において利用してください。
  9. 当サービスでの使用により発生したいかなる損害についても、当社は一切の責任を負いません。
  10. 当サービスはβ版のため、予告なくサービスを終了する場合がございます。
""", unsafe_allow_html=True, )