Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -5,7 +5,7 @@ import gradio as gr
|
|
| 5 |
from huggingface_hub import InferenceClient
|
| 6 |
import requests
|
| 7 |
import time
|
| 8 |
-
import base64 #
|
| 9 |
|
| 10 |
# -----------------------------
|
| 11 |
# Конфигурация GitHub (для приватного репозитория)
|
|
@@ -13,55 +13,64 @@ import base64 # Добавлено для декодирования base64 и
|
|
| 13 |
GITHUB_OWNER = "Tony14100"
|
| 14 |
GITHUB_REPO = "Prompt-Tonic"
|
| 15 |
GITHUB_REF = "main"
|
| 16 |
-
GITHUB_PATH = "OzonConsultant"
|
| 17 |
|
| 18 |
GITHUB_API_URL = f"https://api.github.com/repos/{GITHUB_OWNER}/{GITHUB_REPO}/contents/{GITHUB_PATH}?ref={GITHUB_REF}"
|
| 19 |
|
| 20 |
LOCAL_PROMPT_FILE = "prompt_cache.txt"
|
| 21 |
-
LOCAL_SHA_FILE = "prompt_cache_sha.txt" #
|
| 22 |
|
|
|
|
|
|
|
|
|
|
| 23 |
def load_system_prompt():
|
| 24 |
github_token = os.getenv("GITHUB_TOKEN")
|
| 25 |
if not github_token:
|
| 26 |
-
|
|
|
|
| 27 |
|
| 28 |
headers = {
|
| 29 |
'Authorization': f'token {github_token}',
|
| 30 |
-
'User-Agent': 'Gradio-App-Request'
|
|
|
|
| 31 |
}
|
| 32 |
|
|
|
|
|
|
|
| 33 |
try:
|
| 34 |
-
# Получаем метаданные и содержимое файла через API
|
| 35 |
response = requests.get(GITHUB_API_URL, headers=headers, timeout=10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
response.raise_for_status()
|
| 37 |
data = response.json()
|
| 38 |
|
| 39 |
current_sha = data['sha']
|
| 40 |
-
print(f"[DEBUG]
|
| 41 |
|
| 42 |
-
# Проверяем кэш SHA
|
| 43 |
cached_sha = None
|
| 44 |
if os.path.exists(LOCAL_SHA_FILE):
|
| 45 |
try:
|
| 46 |
with open(LOCAL_SHA_FILE, 'r') as f:
|
| 47 |
cached_sha = f.read().strip()
|
| 48 |
-
print(f"[DEBUG] Кэшированный SHA: {cached_sha}")
|
| 49 |
except Exception as e:
|
| 50 |
-
print(f"Ошибка чтения SHA
|
| 51 |
|
| 52 |
-
# Если SHA не изменился, используем кэш
|
| 53 |
if cached_sha == current_sha and os.path.exists(LOCAL_PROMPT_FILE):
|
| 54 |
try:
|
| 55 |
with open(LOCAL_PROMPT_FILE, 'r', encoding='utf-8') as f:
|
| 56 |
prompt = f.read().strip()
|
| 57 |
if prompt:
|
| 58 |
-
print("
|
| 59 |
return prompt
|
| 60 |
else:
|
| 61 |
raise ValueError("Кэш пустой.")
|
| 62 |
except Exception as e:
|
| 63 |
print(f"Ошибка чтения кэша: {e}")
|
| 64 |
-
# Если ошибка, продолжаем обновление
|
| 65 |
|
| 66 |
# SHA изменился или нет кэша — обновляем
|
| 67 |
print("Обновляем промпт с GitHub (SHA изменился).")
|
|
@@ -69,7 +78,7 @@ def load_system_prompt():
|
|
| 69 |
prompt = base64.b64decode(content_b64).decode('utf-8').strip()
|
| 70 |
|
| 71 |
if not prompt:
|
| 72 |
-
raise ValueError("Промпт пустой.
|
| 73 |
|
| 74 |
# Сохраняем в кэш
|
| 75 |
with open(LOCAL_PROMPT_FILE, 'w', encoding='utf-8') as f:
|
|
@@ -80,17 +89,37 @@ def load_system_prompt():
|
|
| 80 |
print("Промпт обновлён и сохранён в кэш.")
|
| 81 |
return prompt
|
| 82 |
|
| 83 |
-
except requests.exceptions.
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
except Exception as e:
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
SYSTEM_PROMPT = load_system_prompt()
|
| 91 |
print("Загруженный промпт:", SYSTEM_PROMPT[:200] + "..." if len(SYSTEM_PROMPT) > 200 else SYSTEM_PROMPT)
|
| 92 |
|
| 93 |
-
MODEL_ID = "
|
| 94 |
MAX_TOKENS = 512
|
| 95 |
|
| 96 |
# -----------------------------
|
|
@@ -119,7 +148,7 @@ def on_user_message(user_message: str, state: Dict):
|
|
| 119 |
if not state["system_used"]:
|
| 120 |
messages.insert(0, {"role": "system", "content": SYSTEM_PROMPT})
|
| 121 |
state["system_used"] = True
|
| 122 |
-
|
| 123 |
|
| 124 |
messages.append({"role": "user", "content": user_message})
|
| 125 |
assistant_reply = ""
|
|
@@ -134,7 +163,7 @@ def on_user_message(user_message: str, state: Dict):
|
|
| 134 |
stream=False,
|
| 135 |
)
|
| 136 |
assistant_reply = response.choices[0].message["content"].strip()
|
| 137 |
-
print(f"[DEBUG] Ответ модели: {assistant_reply}")
|
| 138 |
except Exception as e:
|
| 139 |
print(f"[DEBUG] Ошибка модели: {e}")
|
| 140 |
assistant_reply = mock_predict(user_message)
|
|
@@ -186,11 +215,12 @@ if __name__ == "__main__":
|
|
| 186 |
except Exception as e:
|
| 187 |
print(f"[WARNING] Проблема с токеном: {e}. Установи HF_TOKEN!")
|
| 188 |
|
| 189 |
-
# Проверяем GITHUB_TOKEN при запуске
|
| 190 |
try:
|
| 191 |
-
load_system_prompt()
|
|
|
|
| 192 |
except Exception as e:
|
| 193 |
-
print(f"[WARNING] Проблема с GITHUB_TOKEN: {e}.
|
| 194 |
|
| 195 |
app.queue(max_size=5)
|
| 196 |
app.launch(server_name="0.0.0.0", server_port=7860, debug=True, share=False)
|
|
|
|
| 5 |
from huggingface_hub import InferenceClient
|
| 6 |
import requests
|
| 7 |
import time
|
| 8 |
+
import base64 # Для декодирования base64 из GitHub API
|
| 9 |
|
| 10 |
# -----------------------------
|
| 11 |
# Конфигурация GitHub (для приватного репозитория)
|
|
|
|
| 13 |
GITHUB_OWNER = "Tony14100"
|
| 14 |
GITHUB_REPO = "Prompt-Tonic"
|
| 15 |
GITHUB_REF = "main"
|
| 16 |
+
GITHUB_PATH = "OzonConsultant" # Убедитесь, что это файл в корне репо
|
| 17 |
|
| 18 |
GITHUB_API_URL = f"https://api.github.com/repos/{GITHUB_OWNER}/{GITHUB_REPO}/contents/{GITHUB_PATH}?ref={GITHUB_REF}"
|
| 19 |
|
| 20 |
LOCAL_PROMPT_FILE = "prompt_cache.txt"
|
| 21 |
+
LOCAL_SHA_FILE = "prompt_cache_sha.txt" # Файл для хранения SHA
|
| 22 |
|
| 23 |
+
# -----------------------------
|
| 24 |
+
# Функция загрузки системного промпта
|
| 25 |
+
# -----------------------------
|
| 26 |
def load_system_prompt():
|
| 27 |
github_token = os.getenv("GITHUB_TOKEN")
|
| 28 |
if not github_token:
|
| 29 |
+
print("[WARNING] GITHUB_TOKEN не найден. Fallback на дефолтный промпт.")
|
| 30 |
+
return "Вы — полезный консультант по Ozon. Отвечайте на вопросы клиентов четко и профессионально." # Дефолтный промпт
|
| 31 |
|
| 32 |
headers = {
|
| 33 |
'Authorization': f'token {github_token}',
|
| 34 |
+
'User-Agent': 'Gradio-App-Request',
|
| 35 |
+
'Accept': 'application/vnd.github.v3+json'
|
| 36 |
}
|
| 37 |
|
| 38 |
+
print(f"[DEBUG] Запрос к: {GITHUB_API_URL}")
|
| 39 |
+
|
| 40 |
try:
|
|
|
|
| 41 |
response = requests.get(GITHUB_API_URL, headers=headers, timeout=10)
|
| 42 |
+
print(f"[DEBUG] Status code: {response.status_code}")
|
| 43 |
+
print(f"[DEBUG] Response headers: {dict(response.headers)[:3]}...") # Первые 3 заголовка для отладки
|
| 44 |
+
|
| 45 |
+
if response.status_code == 404:
|
| 46 |
+
raise RuntimeError(f"404: 'OzonConsultant' не найден. Проверьте: файл существует в корне на 'main'? Это файл (не папка)? Полный путь верный?")
|
| 47 |
+
|
| 48 |
response.raise_for_status()
|
| 49 |
data = response.json()
|
| 50 |
|
| 51 |
current_sha = data['sha']
|
| 52 |
+
print(f"[DEBUG] SHA: {current_sha[:10]}...")
|
| 53 |
|
| 54 |
+
# Проверяем кэш по SHA
|
| 55 |
cached_sha = None
|
| 56 |
if os.path.exists(LOCAL_SHA_FILE):
|
| 57 |
try:
|
| 58 |
with open(LOCAL_SHA_FILE, 'r') as f:
|
| 59 |
cached_sha = f.read().strip()
|
|
|
|
| 60 |
except Exception as e:
|
| 61 |
+
print(f"Ошибка чтения SHA: {e}")
|
| 62 |
|
|
|
|
| 63 |
if cached_sha == current_sha and os.path.exists(LOCAL_PROMPT_FILE):
|
| 64 |
try:
|
| 65 |
with open(LOCAL_PROMPT_FILE, 'r', encoding='utf-8') as f:
|
| 66 |
prompt = f.read().strip()
|
| 67 |
if prompt:
|
| 68 |
+
print("Кэш SHA совпадает — используем локальный промпт.")
|
| 69 |
return prompt
|
| 70 |
else:
|
| 71 |
raise ValueError("Кэш пустой.")
|
| 72 |
except Exception as e:
|
| 73 |
print(f"Ошибка чтения кэша: {e}")
|
|
|
|
| 74 |
|
| 75 |
# SHA изменился или нет кэша — обновляем
|
| 76 |
print("Обновляем промпт с GitHub (SHA изменился).")
|
|
|
|
| 78 |
prompt = base64.b64decode(content_b64).decode('utf-8').strip()
|
| 79 |
|
| 80 |
if not prompt:
|
| 81 |
+
raise ValueError("Промпт пустой. Проверьте файл на GitHub.")
|
| 82 |
|
| 83 |
# Сохраняем в кэш
|
| 84 |
with open(LOCAL_PROMPT_FILE, 'w', encoding='utf-8') as f:
|
|
|
|
| 89 |
print("Промпт обновлён и сохранён в кэш.")
|
| 90 |
return prompt
|
| 91 |
|
| 92 |
+
except requests.exceptions.HTTPError as e:
|
| 93 |
+
status = e.response.status_code if hasattr(e.response, 'status_code') else 0
|
| 94 |
+
if status == 401:
|
| 95 |
+
raise RuntimeError(f"401: Токен неверный/истёк. Создайте новый в GitHub Settings > Developer settings.")
|
| 96 |
+
elif status == 403:
|
| 97 |
+
raise RuntimeError(f"403: Токен без доступа. Добавьте 'Contents: Read' для Prompt-Tonic.")
|
| 98 |
+
else:
|
| 99 |
+
raise RuntimeError(f"HTTP {status}: {e}. Проверьте токен/URL.")
|
| 100 |
except Exception as e:
|
| 101 |
+
print(f"[WARNING] GitHub API failed: {e}. Fallback активирован.")
|
| 102 |
+
|
| 103 |
+
# Fallback 1: Локальный файл (загрузите OzonConsultant.txt в Space)
|
| 104 |
+
local_file = "OzonConsultant.txt"
|
| 105 |
+
if os.path.exists(local_file):
|
| 106 |
+
try:
|
| 107 |
+
with open(local_file, 'r', encoding='utf-8') as f:
|
| 108 |
+
prompt = f.read().strip()
|
| 109 |
+
print(f"Fallback: Загружен локальный {local_file}.")
|
| 110 |
+
return prompt
|
| 111 |
+
except Exception as le:
|
| 112 |
+
print(f"Локальный fallback failed: {le}")
|
| 113 |
+
|
| 114 |
+
# Fallback 2: Дефолтный промпт
|
| 115 |
+
default_prompt = """Вы — полезный консультант по Ozon. Отвечайте на вопросы клиентов четко и профессионально."""
|
| 116 |
+
print("Fallback: Дефолтный промпт (GitHub недоступен). Обновите файл/токен.")
|
| 117 |
+
return default_prompt
|
| 118 |
|
| 119 |
SYSTEM_PROMPT = load_system_prompt()
|
| 120 |
print("Загруженный промпт:", SYSTEM_PROMPT[:200] + "..." if len(SYSTEM_PROMPT) > 200 else SYSTEM_PROMPT)
|
| 121 |
|
| 122 |
+
MODEL_ID = "zai-org/GLM-4.5"
|
| 123 |
MAX_TOKENS = 512
|
| 124 |
|
| 125 |
# -----------------------------
|
|
|
|
| 148 |
if not state["system_used"]:
|
| 149 |
messages.insert(0, {"role": "system", "content": SYSTEM_PROMPT})
|
| 150 |
state["system_used"] = True
|
| 151 |
+
print("[DEBUG] System prompt добавлен в messages.")
|
| 152 |
|
| 153 |
messages.append({"role": "user", "content": user_message})
|
| 154 |
assistant_reply = ""
|
|
|
|
| 163 |
stream=False,
|
| 164 |
)
|
| 165 |
assistant_reply = response.choices[0].message["content"].strip()
|
| 166 |
+
print(f"[DEBUG] Ответ модели: {assistant_reply[:50]}...")
|
| 167 |
except Exception as e:
|
| 168 |
print(f"[DEBUG] Ошибка модели: {e}")
|
| 169 |
assistant_reply = mock_predict(user_message)
|
|
|
|
| 215 |
except Exception as e:
|
| 216 |
print(f"[WARNING] Проблема с токеном: {e}. Установи HF_TOKEN!")
|
| 217 |
|
| 218 |
+
# Проверяем GITHUB_TOKEN при запуске (но не краш, если fallback)
|
| 219 |
try:
|
| 220 |
+
# load_system_prompt() уже вызвано выше
|
| 221 |
+
pass
|
| 222 |
except Exception as e:
|
| 223 |
+
print(f"[WARNING] Проблема с GITHUB_TOKEN: {e}. Fallback активен!")
|
| 224 |
|
| 225 |
app.queue(max_size=5)
|
| 226 |
app.launch(server_name="0.0.0.0", server_port=7860, debug=True, share=False)
|