Spaces:
Sleeping
Sleeping
File size: 5,313 Bytes
1155486 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | import os
import numpy as np
import pandas as pd
from functools import wraps
from dotenv import load_dotenv # dotenvをインポート
from flask import Flask, render_template, request, session, redirect, url_for
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import csv
from datetime import datetime
import pytz
load_dotenv() # .envファイルを読み込む
app = Flask(__name__)
# 環境変数からSECRET_KEYを読み込む
app.secret_key = os.environ.get('SECRET_KEY')
# --- 質問を保存するCSVファイル ---
LOG_FILE = 'logged_questions.csv'
# --- AIモデルとデータの読み込み(サーバー起動時に一度だけ実行)---
try:
# モデルの読み込み
# model = SentenceTransformer('stsb-xlm-r-multilingual')
model = SentenceTransformer('pkshatech/GLuCoSE-base-ja')
# ベクトルデータの読み込み
question_vectors = np.load('question_vectors.npy')
# Q&Aデータの読み込み
qa_df = pd.read_csv('qa_data.csv')
print("モデルとデータの読み込みに成功しました。")
except Exception as e:
print(f"モデルまたはデータの読み込みに失敗しました: {e}")
model = None
def login_required(f):
@wraps(f)
def decorated_view(*args, **kwargs):
if 'logged_in' not in session:
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_view
@app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
# 環境変数からパスワードを読み込む
if request.form['password'] == os.environ.get('SITE_PASSWORD'):
session['logged_in'] = True
return redirect(url_for('home'))
else:
error = 'パスワードが正しくありません'
return render_template('login.html', error=error)
@app.route('/logout')
def logout():
session.pop('logged_in', None)
return redirect(url_for('login'))
@app.route('/')
@login_required
def home():
phone_number = os.environ.get('PHONE_NUMBER')
return render_template('index.html', phone_number=phone_number)
@app.route('/documents')
@login_required
def documents():
uploads_dir = os.path.join(app.static_folder, 'uploads')
files = []
if os.path.exists(uploads_dir):
supportted_extensions = {'.pdf', '.png'}
files = [f for f in os.listdir(uploads_dir) if os.path.splitext(f)[1].lower() in supportted_extensions]
return render_template('documents.html', files=files)
# 新しく追加するルート
@app.route('/backstand_entrance')
@login_required
def backstand_entrance():
return render_template('backstand_entrance.html')
@app.route('/backstand_inside')
@login_required
def backstand_inside():
return render_template('backstand_inside.html')
@app.route('/sofa-seat')
@login_required
def third_floor_seats():
return render_template('sofa-seat.html')
@app.route('/faq')
@login_required
def faq():
return render_template('faq.html')
@app.route('/ask', methods=['GET', 'POST'])
@login_required
def ask():
answer = None
question = ""
error = None
if model is None:
error = "AIモデルの読み込みに失敗したため、現在この機能を使用できません。"
return render_template('ask.html', error=error)
if request.method == 'POST':
question = request.form['question']
if question:
# --- ここから質問を保存する処理 ---
try:
# 日本時間を取得
jst = pytz.timezone('Asia/Tokyo')
timestamp = datetime.now(jst).strftime('%Y-%m-%d %H:%M:%S')
# ファイルが空かどうかの確認
file_exists = os.path.isfile(LOG_FILE) and os.path.getsize(LOG_FILE) > 0
# ファイルに追記モードで書き込み
with open(LOG_FILE, 'a', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
# ファイルが空の場合、ヘッダーを書き込む
if not file_exists:
writer.writerow(['timestamp', 'question'])
writer.writerow([timestamp, question])
except Exception as e:
print(f"質問の保存中にエラーが発生しました: {e}")
# --- ここまで ---
# 1. ユーザーの質問をベクトル化
user_vector = model.encode([question], convert_to_numpy=True)
# 2. コサイン類似度を計算
similarities = cosine_similarity(user_vector, question_vectors)
# 3. 最も類似度が高い質問のインデックスを取得
most_similar_index = np.argmax(similarities)
# 4. 対応する答えを取得
answer = qa_df.iloc[most_similar_index]['answer']
return render_template('ask.html', question=question, answer=answer)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0') |