sirochild commited on
Commit
948e4c7
·
verified ·
1 Parent(s): 9ca61bb

Upload 3 files

Browse files
Files changed (3) hide show
  1. main_app.py +26 -15
  2. persistent_user_manager.py +84 -73
  3. requirements.txt +3 -2
main_app.py CHANGED
@@ -19,6 +19,20 @@ if sys.platform.startswith('win'):
19
  # .envファイルから環境変数を読み込み
20
  load_dotenv()
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  # ロガー設定
23
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
24
  logger = logging.getLogger(__name__)
@@ -504,32 +518,29 @@ def initialize_session_state(managers, force_reset_override=False):
504
  user_id_manager = managers["user_id_manager"] # フォールバック用
505
  session_api_client = managers["session_api_client"]
506
 
507
- # セッションIDを取得または生成(重複防止・統一化)
508
  # 重複ID生成防止: 既にuser_idがあり、force_resetでない場合は既存IDを使用
509
  if 'user_id' in st.session_state and not force_reset:
510
  session_id = st.session_state.user_id
511
  logger.debug(f"既存ユーザーID使用(rerun対応): {session_id[:8]}...")
512
  else:
513
- # 新規作成またはリセット時のみ
514
- session_id = None
515
-
516
  try:
517
- # 永続ストレージからCookieベースでユーザーIDを取得
518
- session_id = persistent_user_manager.get_or_create_user_id()
519
- logger.info(f"永続ストレージからユーザーIDを取得: {session_id[:8]}...")
520
  except Exception as e:
521
- logger.warning(f"永続ストレージ取得エラー、フォールバック使用: {e}")
522
 
 
523
  try:
524
- # フォールバック: 従来のローカルファイル方式
525
  session_id = user_id_manager.get_or_create_user_id()
526
- logger.info(f"フォールバック: ローカルファイルからユーザーIDを取得: {session_id[:8]}...")
527
  except Exception as e2:
528
- logger.error(f"フォールバックも失敗: {e2}")
529
- # 最終フォールバック: 一時的なIDを生成
530
- import uuid
531
- session_id = str(uuid.uuid4())
532
- logger.warning(f"最終フォールバック: 一時的なIDを生成: {session_id[:8]}...")
533
 
534
  # ユーザーIDとしてセッションIDを使用
535
  session_changed = ('user_id' not in st.session_state or
 
19
  # .envファイルから環境変数を読み込み
20
  load_dotenv()
21
 
22
+ # PyTorchのクラス登録問題を回避するための設定
23
+ try:
24
+ import torch
25
+ # スレッド数を制限してクラス登録問題を回避
26
+ torch.set_num_threads(int(os.getenv("TORCH_NUM_THREADS", "1")))
27
+ # 警告を抑制
28
+ import warnings
29
+ warnings.filterwarnings("ignore", category=UserWarning, module="torch")
30
+ logger.info("PyTorch初期化設定完了")
31
+ except ImportError:
32
+ logger.info("PyTorchが利用できません - ルールベース処理を使用")
33
+ except Exception as e:
34
+ logger.warning(f"PyTorch初期化設定エラー: {e}")
35
+
36
  # ロガー設定
37
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
38
  logger = logging.getLogger(__name__)
 
518
  user_id_manager = managers["user_id_manager"] # フォールバック用
519
  session_api_client = managers["session_api_client"]
520
 
521
+ # Cookie認証ベースのユーザーID取得(起動時uuid4()生成を排除)
522
  # 重複ID生成防止: 既にuser_idがあり、force_resetでない場合は既存IDを使用
523
  if 'user_id' in st.session_state and not force_reset:
524
  session_id = st.session_state.user_id
525
  logger.debug(f"既存ユーザーID使用(rerun対応): {session_id[:8]}...")
526
  else:
527
+ # Cookie認証ベースでユーザーIDを取得(新規作成またはリセット時のみ)
 
 
528
  try:
529
+ # Cookie認証を最優先で使用
530
+ session_id = persistent_user_manager.get_or_create_user_id(force_reset=force_reset)
531
+ logger.info(f"Cookie認証ベースユーザーID取得: {session_id[:8]}...")
532
  except Exception as e:
533
+ logger.error(f"Cookie認証失敗: {e}")
534
 
535
+ # フォールバック: 従来のローカルファイル方式(uuid4()生成を避ける)
536
  try:
 
537
  session_id = user_id_manager.get_or_create_user_id()
538
+ logger.warning(f"フォールバック: ローカルファイル方式使用: {session_id[:8]}...")
539
  except Exception as e2:
540
+ logger.error(f"全ての認証方式が失敗: {e2}")
541
+ # 最終フォールバック: セッション固有の一時的なIDを生成(起動時uuid4()を避ける)
542
+ session_id = f"temp_{id(st.session_state)}"
543
+ logger.warning(f"最終フォールバック: セッション固有一時ID: {session_id}")
 
544
 
545
  # ユーザーIDとしてセッションIDを使用
546
  session_changed = ('user_id' not in st.session_state or
persistent_user_manager.py CHANGED
@@ -57,19 +57,21 @@ class PersistentUserManager:
57
  logger.warning(f"フォールバック: ローカルディレクトリを使用 {self.user_data_dir}")
58
 
59
  def _ensure_cookie_manager(self, force_init: bool = False):
60
- """Cookie管理システムの初期化(初回またはフルリセット時のみ)"""
61
  # 既に初期化済みで、強制初期化でない場合はスキップ
62
  if self._cookie_initialized and not force_init:
 
63
  return
64
 
65
- # アプリ全体でのCookie初期化状態をチェック(グローバルフラグ)
66
- if not force_init and st.session_state.get('cookie_manager_initialized', False):
67
- logger.debug("Cookie管理システム既に初期化済み - スキップ")
 
68
  self._cookie_initialized = True
69
  return
70
 
71
  try:
72
- logger.info("Cookie管理システム初期化開始...")
73
 
74
  # セキュアなパスワードを生成(環境変数から取得、なければ生成)
75
  cookie_password = os.getenv("MARI_COOKIE_PASSWORD", "mari_chat_secure_key_2024")
@@ -81,26 +83,27 @@ class PersistentUserManager:
81
 
82
  # Cookieが準備できるまで待機
83
  if not cookies.ready():
 
84
  st.stop()
85
 
86
  self.cookies = cookies
87
  self._cookie_initialized = True
88
 
89
- # グローバルフラグを設定(アプリ全体で一度だけ初期化)
90
- st.session_state.cookie_manager_initialized = True
91
 
92
- logger.info("Cookie管理システム初期化完了")
93
 
94
  except Exception as e:
95
  logger.error(f"Cookie管理初期化エラー: {e}")
96
  # フォールバック: セッション状態のみ使用
97
  self.cookies = None
98
  self._cookie_initialized = True
99
- st.session_state.cookie_manager_initialized = True
100
 
101
  def get_or_create_user_id(self, force_reset: bool = False) -> str:
102
  """
103
- ユーザーIDを取得または新規作成(Cookie連携・重複防止)
104
 
105
  Args:
106
  force_reset: フルリセット時のみTrue
@@ -109,69 +112,52 @@ class PersistentUserManager:
109
  ユーザーID
110
  """
111
  try:
112
- # 最優先: 既にStreamlitセッション状態にuser_idがある場合はそれを使用(フルリセット以外)
113
  if not force_reset and 'user_id' in st.session_state:
114
  existing_id = st.session_state.user_id
115
  if existing_id and self._is_valid_uuid(existing_id):
116
- logger.debug(f"Streamlitセッション状態からユーザーID使用: {existing_id[:8]}...")
117
  return existing_id
118
 
119
- # 重複チェック防止: 既にセッション状態にある場合はそれを使用(フルリセット以外)
120
- if not force_reset and hasattr(st.session_state, 'persistent_user_id_checked'):
121
- existing_id = st.session_state.get('persistent_user_id')
122
- if existing_id and self._is_valid_uuid(existing_id):
123
- logger.debug(f"既にチェック済みのユーザーID使用: {existing_id[:8]}...")
124
- return existing_id
125
 
126
- # Cookie初期化は初回またはフルリセット時のみ
127
- if not self._cookie_initialized or force_reset:
128
- # 1. Cookieから��ーザーIDを取得
129
- user_id = self._get_user_id_from_cookie()
130
-
131
- if user_id and self._is_valid_user_id(user_id):
132
- # 有効なユーザーIDが存在
133
- self._update_user_access_time(user_id)
134
- st.session_state.persistent_user_id = user_id
135
- st.session_state.persistent_user_id_checked = True
136
- logger.info(f"CookieからユーザーID取得: {user_id[:8]}...")
137
- return user_id
138
-
139
- # 2. セッション状態から取得を試行(Cookieが無効な場合のみ)
140
- if not force_reset:
141
- user_id = st.session_state.get('persistent_user_id')
142
- if user_id and self._is_valid_user_id(user_id):
143
- # セッション状態にあるIDを使用してCookieを更新
144
- self._set_user_id_cookie(user_id)
145
- self._update_user_access_time(user_id)
146
- st.session_state.persistent_user_id_checked = True
147
- logger.info(f"セッション状態からユーザーID復元: {user_id[:8]}...")
148
- return user_id
149
-
150
- # 3. 新規ユーザーIDを作成
151
- user_id = self._create_new_user()
152
- st.session_state.persistent_user_id_checked = True
153
- logger.info(f"新規ユーザーID作成: {user_id[:8]}...")
154
  return user_id
155
- else:
156
- # Cookie初期化済みの場合は、セッション状態から取得
157
- existing_id = st.session_state.get('persistent_user_id')
158
- if existing_id and self._is_valid_uuid(existing_id):
159
- logger.debug(f"Cookie初期化済み - セッション状態からユーザーID使用: {existing_id[:8]}...")
160
- return existing_id
161
-
162
- # フォールバック: 新規作成
163
- user_id = self._create_new_user()
164
- st.session_state.persistent_user_id_checked = True
165
- logger.info(f"フォールバック新規ユーザーID作成: {user_id[:8]}...")
 
166
  return user_id
167
 
 
 
 
 
 
 
168
  except Exception as e:
169
- logger.error(f"ユーザーID取得エラー: {e}")
170
- # フォールバック: 一時的なIDを生成
171
- fallback_id = str(uuid.uuid4())
172
- st.session_state.persistent_user_id = fallback_id
173
- st.session_state.persistent_user_id_checked = True
174
- return fallback_id
175
 
176
  def _get_user_id_from_cookie(self) -> Optional[str]:
177
  """CookieからユーザーIDを取得"""
@@ -239,8 +225,8 @@ class PersistentUserManager:
239
  logger.warning(f"ユーザーID検証エラー: {e}")
240
  return False
241
 
242
- def _create_new_user(self) -> str:
243
- """新規ユーザーを作成"""
244
  try:
245
  user_id = str(uuid.uuid4())
246
 
@@ -250,6 +236,7 @@ class PersistentUserManager:
250
  "created_at": datetime.now().isoformat(),
251
  "last_access": datetime.now().isoformat(),
252
  "version": "1.0",
 
253
  "game_data": {
254
  "affection": 30,
255
  "messages": [{"role": "assistant", "content": "何の用?遊びに来たの?", "is_initial": True}],
@@ -267,19 +254,43 @@ class PersistentUserManager:
267
  with open(user_file, 'w', encoding='utf-8') as f:
268
  json.dump(user_data, f, ensure_ascii=False, indent=2)
269
 
270
- # Cookieとセッション状態に保存
271
  self._set_user_id_cookie(user_id)
272
- st.session_state.persistent_user_id = user_id
273
 
274
- logger.info(f"新規ユーザー作成完了: {user_id[:8]}...")
 
 
 
275
  return user_id
276
 
277
  except Exception as e:
278
- logger.error(f"新規ユーザー作成エラー: {e}")
279
- # フォールバック
280
- fallback_id = str(uuid.uuid4())
281
- st.session_state.persistent_user_id = fallback_id
282
- return fallback_id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
  def _update_user_access_time(self, user_id: str):
285
  """ユーザーの最終アクセス時刻を更新"""
 
57
  logger.warning(f"フォールバック: ローカルディレクトリを使用 {self.user_data_dir}")
58
 
59
  def _ensure_cookie_manager(self, force_init: bool = False):
60
+ """Cookie管理システムの初期化(ブラウザごとに一度だけ)"""
61
  # 既に初期化済みで、強制初期化でない場合はスキップ
62
  if self._cookie_initialized and not force_init:
63
+ logger.debug("Cookie管理システム既に初期化済み")
64
  return
65
 
66
+ # ブラウザセッション単位でのCookie初期化チェック
67
+ browser_session_key = f"cookie_initialized_{id(st.session_state)}"
68
+ if not force_init and st.session_state.get(browser_session_key, False):
69
+ logger.debug("このブラウザセッションでCookie管理システム既に初期化済み")
70
  self._cookie_initialized = True
71
  return
72
 
73
  try:
74
+ logger.info("Cookie管理システム初期化開始(ブラウザセッション単位)...")
75
 
76
  # セキュアなパスワードを生成(環境変数から取得、なければ生成)
77
  cookie_password = os.getenv("MARI_COOKIE_PASSWORD", "mari_chat_secure_key_2024")
 
83
 
84
  # Cookieが準備できるまで待機
85
  if not cookies.ready():
86
+ logger.warning("Cookie準備中 - 待機")
87
  st.stop()
88
 
89
  self.cookies = cookies
90
  self._cookie_initialized = True
91
 
92
+ # ブラウザセッション単位でフラグを設定
93
+ st.session_state[browser_session_key] = True
94
 
95
+ logger.info("Cookie管理システム初期化完了(ブラウザセッション単位)")
96
 
97
  except Exception as e:
98
  logger.error(f"Cookie管理初期化エラー: {e}")
99
  # フォールバック: セッション状態のみ使用
100
  self.cookies = None
101
  self._cookie_initialized = True
102
+ st.session_state[browser_session_key] = True
103
 
104
  def get_or_create_user_id(self, force_reset: bool = False) -> str:
105
  """
106
+ Cookie認証ベースのユーザーID取得(ブラウザごとに一つのCookie
107
 
108
  Args:
109
  force_reset: フルリセット時のみTrue
 
112
  ユーザーID
113
  """
114
  try:
115
+ # フルリセット時以外で、既にセッション状態にuser_idがある場合はそれを使用
116
  if not force_reset and 'user_id' in st.session_state:
117
  existing_id = st.session_state.user_id
118
  if existing_id and self._is_valid_uuid(existing_id):
119
+ logger.debug(f"セッション状態からユーザーID使用: {existing_id[:8]}...")
120
  return existing_id
121
 
122
+ # Cookie管理システムを初期化(ブラウザごとに一度だけ)
123
+ self._ensure_cookie_manager(force_init=force_reset)
 
 
 
 
124
 
125
+ # 1. CookieからユーザーIDを取得(最優先)
126
+ user_id = self._get_user_id_from_cookie()
127
+
128
+ if user_id and self._is_valid_user_id(user_id):
129
+ # 有効なCookieベースのユーザーIDが存在
130
+ self._update_user_access_time(user_id)
131
+ st.session_state.user_id = user_id # セッション状態に保存
132
+ logger.info(f"Cookie認証成功: {user_id[:8]}...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  return user_id
134
+
135
+ # 2. Cookieが無効または存在しない場合は新規作成
136
+ if force_reset or not user_id:
137
+ user_id = self._create_new_user_with_cookie()
138
+ logger.info(f"新規Cookie認証ユーザー作成: {user_id[:8]}...")
139
+ return user_id
140
+
141
+ # 3. 最終フォールバック(Cookieが無効だが何らかのIDがある場合)
142
+ if user_id and self._is_valid_uuid(user_id):
143
+ # UUIDとして有効だが、ユーザーファイルが存在しない場合は新規作成
144
+ user_id = self._create_new_user_with_cookie()
145
+ logger.info(f"フォールバック新規ユーザー作成: {user_id[:8]}...")
146
  return user_id
147
 
148
+ # 4. 完全フォールバック(Cookie無効時)
149
+ logger.warning("Cookie認証失敗 - 一時的なセッションIDを使用")
150
+ temp_id = str(uuid.uuid4())
151
+ st.session_state.user_id = temp_id
152
+ return temp_id
153
+
154
  except Exception as e:
155
+ logger.error(f"Cookie認証エラー: {e}")
156
+ # 完全フォールバック: 一時的なIDを生成(Cookieに保存しない)
157
+ temp_id = str(uuid.uuid4())
158
+ st.session_state.user_id = temp_id
159
+ logger.warning(f"一時的なセッションID使用: {temp_id[:8]}...")
160
+ return temp_id
161
 
162
  def _get_user_id_from_cookie(self) -> Optional[str]:
163
  """CookieからユーザーIDを取得"""
 
225
  logger.warning(f"ユーザーID検証エラー: {e}")
226
  return False
227
 
228
+ def _create_new_user_with_cookie(self) -> str:
229
+ """Cookie認証ベースの新���ユーザーを作成"""
230
  try:
231
  user_id = str(uuid.uuid4())
232
 
 
236
  "created_at": datetime.now().isoformat(),
237
  "last_access": datetime.now().isoformat(),
238
  "version": "1.0",
239
+ "browser_fingerprint": self._generate_browser_fingerprint(),
240
  "game_data": {
241
  "affection": 30,
242
  "messages": [{"role": "assistant", "content": "何の用?遊びに来たの?", "is_initial": True}],
 
254
  with open(user_file, 'w', encoding='utf-8') as f:
255
  json.dump(user_data, f, ensure_ascii=False, indent=2)
256
 
257
+ # Cookieに保存(ブラウザごとに一つ)
258
  self._set_user_id_cookie(user_id)
 
259
 
260
+ # セッション状態に保存
261
+ st.session_state.user_id = user_id
262
+
263
+ logger.info(f"Cookie認証ベース新規ユーザー作成完了: {user_id[:8]}...")
264
  return user_id
265
 
266
  except Exception as e:
267
+ logger.error(f"Cookie認証ベース新規ユーザー作成エラー: {e}")
268
+ # フォールバック: 一時的なIDを生成(Cookieに保存しない)
269
+ temp_id = str(uuid.uuid4())
270
+ st.session_state.user_id = temp_id
271
+ logger.warning(f"フォールバック一時ID: {temp_id[:8]}...")
272
+ return temp_id
273
+
274
+ def _create_new_user(self) -> str:
275
+ """従来の新規ユーザー作成(後方互換性のため残す)"""
276
+ return self._create_new_user_with_cookie()
277
+
278
+ def _generate_browser_fingerprint(self) -> str:
279
+ """ブラウザフィンガープリントを生成(簡易版)"""
280
+ try:
281
+ # Streamlitのセッション情報を使用してフィンガープリントを生成
282
+ import hashlib
283
+
284
+ # セッション固有の情報を組み合わせ
285
+ session_info = f"{id(st.session_state)}_{datetime.now().strftime('%Y%m%d')}"
286
+ fingerprint = hashlib.md5(session_info.encode()).hexdigest()[:16]
287
+
288
+ logger.debug(f"ブラウザフィンガープリント生成: {fingerprint}")
289
+ return fingerprint
290
+
291
+ except Exception as e:
292
+ logger.warning(f"ブラウザフィンガープリント生成エラー: {e}")
293
+ return "unknown_browser"
294
 
295
  def _update_user_access_time(self, user_id: str):
296
  """ユーザーの最終アクセス時刻を更新"""
requirements.txt CHANGED
@@ -6,8 +6,9 @@ groq>=0.4.0
6
  requests>=2.31.0
7
  unidic-lite
8
  typing-extensions>=4.0.0
9
- transformers>=4.20.0
10
- torch>=1.12.0
 
11
  sentencepiece>=0.1.95
12
  fugashi>=1.1.0
13
  ipadic>=1.0.0
 
6
  requests>=2.31.0
7
  unidic-lite
8
  typing-extensions>=4.0.0
9
+ # PyTorchとTransformers(クラス登録問題対応版)
10
+ torch>=1.12.0,<2.0.0
11
+ transformers>=4.20.0,<5.0.0
12
  sentencepiece>=0.1.95
13
  fugashi>=1.1.0
14
  ipadic>=1.0.0