Jacek Zadrożny commited on
Commit
637ed9b
·
1 Parent(s): ed669a0

Fix HuggingFace deployment issues

Browse files

- Remove blocking vector_store.connect() call
- Add lazy database connection with timeout
- Add conditional API key validation for HF Spaces
- Add detailed error logging with traceback
- Add timeout to agent initialization (30s)
- Fix test_startup.py for new architecture
- Add HUGGINGFACE_DEBUG.md documentation
- Improve error handling in VectorStoreClient

HUGGINGFACE_DEBUG.md ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🔍 Debugging Hugging Face Spaces Deployment
2
+
3
+ ## Częste Problemy i Rozwiązania
4
+
5
+ ### Problem 1: Runtime Error - Exit code: 0
6
+ **Objawy:**
7
+ ```
8
+ Container logs:
9
+ ===== Application Startup at 2025-12-13 12:09:26 =====
10
+ 2025-12-13 13:09:40.467 | INFO | __main__:<module>:161 - 🚀 Starting Gradio app...
11
+ [aplikacja się zawiesza]
12
+ ```
13
+
14
+ **Przyczyny:**
15
+ 1. **Podwójny start aplikacji** - HF Spaces uruchamia aplikację dwukrotnie podczas budowy kontenera
16
+ 2. **Blokada na połączeniu z bazą danych** - Próba zapisu do LanceDB bez uprawnień
17
+ 3. **Brak API key** - Walidacja konfiguracji blokuje inicjalizację
18
+ 4. **Timeout** - Inicjalizacja trwa zbyt długo (>60s)
19
+
20
+ **Rozwiązania zastosowane w projekcie:**
21
+
22
+ #### 1. Leniwą inicjalizację połączenia z bazą
23
+ ```python
24
+ # ❌ PRZED - blokujące połączenie
25
+ vector_store = VectorStoreClient(uri="./lancedb")
26
+ vector_store.connect() # Blokuje na HF Spaces!
27
+
28
+ # ✅ PO - leniwe połączenie
29
+ vector_store = VectorStoreClient(uri="./lancedb")
30
+ # Połączenie następuje przy pierwszym użyciu
31
+ ```
32
+
33
+ #### 2. Warunkową walidację API key
34
+ ```python
35
+ @field_validator("openai_api_key")
36
+ @classmethod
37
+ def validate_api_key(cls, v):
38
+ v = v or ""
39
+ v = v.strip()
40
+ if not v:
41
+ # Nie rzucaj błędu na HF Spaces
42
+ if not os.getenv("SPACE_ID"):
43
+ raise ValueError("OPENAI_API_KEY is required")
44
+ return v
45
+ ```
46
+
47
+ #### 3. Timeout dla inicjalizacji agenta
48
+ ```python
49
+ def initialize_agent_background():
50
+ """Inicjalizacja z 30-sekundowym timeoutem."""
51
+ def timeout_handler(signum, frame):
52
+ raise TimeoutError("Timeout after 30 seconds")
53
+
54
+ if hasattr(signal, 'SIGALRM'):
55
+ signal.signal(signal.SIGALRM, timeout_handler)
56
+ signal.alarm(30)
57
+
58
+ agent_instance = create_agent()
59
+
60
+ if hasattr(signal, 'SIGALRM'):
61
+ signal.alarm(0)
62
+ ```
63
+
64
+ #### 4. Bezpieczne tworzenie katalogów
65
+ ```python
66
+ @property
67
+ def db(self):
68
+ if self._db is None:
69
+ try:
70
+ os.makedirs(self.uri, exist_ok=True)
71
+ except Exception as e:
72
+ logger.warning(f"Could not create directory: {e}")
73
+
74
+ self._db = lancedb.connect(self.uri)
75
+ return self._db
76
+ ```
77
+
78
+ ### Problem 2: Aplikacja startuje ale nie odpowiada
79
+
80
+ **Przyczyna:** Agent nie zainicjalizował się w tle
81
+
82
+ **Rozwiązanie:**
83
+ - Sprawdź logi w HF Spaces - szukaj `✅ A11y Expert Agent is ready!`
84
+ - Jeśli brak, sprawdź czy nie ma błędu inicjalizacji
85
+ - Aplikacja pokazuje status inicjalizacji w interfejsie
86
+
87
+ ### Problem 3: Brak dostępu do bazy danych
88
+
89
+ **Przyczyna:** Katalog `lancedb/` nie jest w repozytorium lub nie jest śledzony przez Git LFS
90
+
91
+ **Rozwiązanie:**
92
+ ```bash
93
+ # Sprawdź czy lancedb jest w repo
94
+ git lfs ls-files | grep lancedb
95
+
96
+ # Jeśli nie, dodaj do LFS
97
+ git lfs track "lancedb/**"
98
+ git add .gitattributes lancedb/
99
+ git commit -m "Add LanceDB to LFS"
100
+ git push
101
+ ```
102
+
103
+ ### Problem 4: API Key nie jest ustawiony
104
+
105
+ **Objawy:**
106
+ ```
107
+ ❌ Failed to initialize agent: OPENAI_API_KEY is required
108
+ ```
109
+
110
+ **Rozwiązanie:**
111
+ 1. Idź do ustawień swojego Space
112
+ 2. Wybierz zakładkę **Settings** → **Repository secrets**
113
+ 3. Dodaj secret `OPENAI_API_KEY` z wartością twojego klucza
114
+ 4. Zrestartuj Space
115
+
116
+ ## Testowanie lokalne przed wdrożeniem
117
+
118
+ ```bash
119
+ # Test wszystkich komponentów
120
+ python test_startup.py
121
+
122
+ # Test aplikacji Gradio
123
+ python app.py
124
+ ```
125
+
126
+ ## Sprawdzanie logów na HF Spaces
127
+
128
+ 1. **Podczas budowy:**
129
+ - Kliknij na swój Space
130
+ - Przejdź do zakładki **Logs**
131
+ - Szukaj błędów podczas `Building` i `Running`
132
+
133
+ 2. **Podczas działania:**
134
+ - Logi są na żywo w zakładce **Logs**
135
+ - Szukaj komunikatów ERROR lub stacktrace'ów
136
+
137
+ ## Debugowanie z kodem
138
+
139
+ ### Dodaj więcej logowania:
140
+ ```python
141
+ import traceback
142
+ try:
143
+ # twój kod
144
+ except Exception as e:
145
+ logger.error(f"Error: {e}")
146
+ logger.error(traceback.format_exc())
147
+ ```
148
+
149
+ ### Sprawdź zmienne środowiskowe:
150
+ ```python
151
+ import os
152
+ logger.info(f"SPACE_ID: {os.getenv('SPACE_ID')}")
153
+ logger.info(f"HF environment: {os.getenv('SYSTEM')}")
154
+ ```
155
+
156
+ ## Checklist przed wdrożeniem
157
+
158
+ - [ ] `python test_startup.py` przechodzi bez błędów
159
+ - [ ] Baza danych `lancedb/` jest w repo i śledzona przez Git LFS
160
+ - [ ] Secret `OPENAI_API_KEY` jest ustawiony w HF Spaces
161
+ - [ ] `README.md` ma prawidłową konfigurację YAML na górze
162
+ - [ ] `.gitignore` nie blokuje ważnych plików
163
+ - [ ] `requirements.txt` zawiera wszystkie zależności
164
+
165
+ ## Przydatne komendy
166
+
167
+ ```bash
168
+ # Sprawdź rozmiar bazy danych
169
+ du -sh lancedb/
170
+
171
+ # Sprawdź pliki LFS
172
+ git lfs ls-files
173
+
174
+ # Wymuś rebuild Space na HF
175
+ # (w ustawieniach Space → Factory reboot)
176
+ ```
177
+
178
+ ## Kontakt i Wsparcie
179
+
180
+ Jeśli nadal masz problemy:
181
+ 1. Sprawdź pełne logi w zakładce Logs na HF Spaces
182
+ 2. Porównaj z working example na https://huggingface.co/spaces/jacekAI/a11y-expert
183
+ 3. Otwórz issue w repozytorium z pełnymi logami
agent/a11y_agent.py CHANGED
@@ -177,9 +177,8 @@ def create_agent(language: Optional[str] = None) -> A11yExpertAgent:
177
 
178
  settings = get_settings()
179
 
180
- # Create and connect clients
181
  vector_store = VectorStoreClient(uri=settings.lancedb_uri)
182
- vector_store.connect()
183
 
184
  api_key = settings.openai_api_key
185
 
 
177
 
178
  settings = get_settings()
179
 
180
+ # Create vector store with lazy connection
181
  vector_store = VectorStoreClient(uri=settings.lancedb_uri)
 
182
 
183
  api_key = settings.openai_api_key
184
 
app.py CHANGED
@@ -32,15 +32,41 @@ agent_error = None
32
 
33
  # --- Agent Initialization ---
34
  def initialize_agent_background():
35
- """Initialize the agent in background thread."""
36
  global agent_instance, agent_ready, agent_error
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  try:
38
- logger.info("🔄 Starting agent initialization in background...")
39
- agent_instance = create_agent()
40
- agent_ready = True
41
- logger.success("✅ A11y Expert Agent is ready!")
42
  except Exception as e:
43
- logger.error(f"❌ Failed to initialize agent: {e}")
44
  agent_error = str(e)
45
  agent_instance = None
46
 
 
32
 
33
  # --- Agent Initialization ---
34
  def initialize_agent_background():
35
+ """Initialize the agent in background thread with timeout."""
36
  global agent_instance, agent_ready, agent_error
37
+
38
+ def _init_with_timeout():
39
+ import time
40
+ import signal
41
+
42
+ def timeout_handler(signum, frame):
43
+ raise TimeoutError("Agent initialization timed out after 30 seconds")
44
+
45
+ try:
46
+ # Set 30 second timeout for Unix-like systems
47
+ if hasattr(signal, 'SIGALRM'):
48
+ signal.signal(signal.SIGALRM, timeout_handler)
49
+ signal.alarm(30)
50
+
51
+ logger.info("🔄 Starting agent initialization in background...")
52
+ time.sleep(2)
53
+ agent_instance = create_agent()
54
+ agent_ready = True
55
+ logger.success("✅ A11y Expert Agent is ready!")
56
+
57
+ # Cancel timeout
58
+ if hasattr(signal, 'SIGALRM'):
59
+ signal.alarm(0)
60
+
61
+ except Exception as e:
62
+ logger.error(f"❌ Failed to initialize agent: {e}")
63
+ import traceback
64
+ logger.error(traceback.format_exc())
65
+ raise
66
+
67
  try:
68
+ _init_with_timeout()
 
 
 
69
  except Exception as e:
 
70
  agent_error = str(e)
71
  agent_instance = None
72
 
config.py CHANGED
@@ -109,10 +109,12 @@ class Settings(BaseSettings):
109
  v = v or ""
110
  v = v.strip()
111
  if not v:
112
- raise ValueError(
113
- "OPENAI_API_KEY is required. "
114
- "Set it in your .env file or environment variables."
115
- )
 
 
116
  return v
117
 
118
  @field_validator("log_level")
 
109
  v = v or ""
110
  v = v.strip()
111
  if not v:
112
+ import os
113
+ if not os.getenv("SPACE_ID"):
114
+ raise ValueError(
115
+ "OPENAI_API_KEY is required. "
116
+ "Set it in your .env file or environment variables."
117
+ )
118
  return v
119
 
120
  @field_validator("log_level")
database/vector_store_client.py CHANGED
@@ -57,9 +57,20 @@ class VectorStoreClient:
57
  LanceDB database connection
58
  """
59
  if self._db is None:
 
60
  logger.info(f"Connecting to LanceDB at: {self.uri}")
61
- self._db = lancedb.connect(self.uri)
62
- logger.info("✅ Connected to LanceDB")
 
 
 
 
 
 
 
 
 
 
63
  return self._db
64
 
65
  @property
 
57
  LanceDB database connection
58
  """
59
  if self._db is None:
60
+ import os
61
  logger.info(f"Connecting to LanceDB at: {self.uri}")
62
+
63
+ try:
64
+ os.makedirs(self.uri, exist_ok=True)
65
+ except Exception as e:
66
+ logger.warning(f"Could not create directory {self.uri}: {e}")
67
+
68
+ try:
69
+ self._db = lancedb.connect(self.uri)
70
+ logger.info("✅ Connected to LanceDB")
71
+ except Exception as e:
72
+ logger.error(f"Failed to connect to LanceDB: {e}")
73
+ raise
74
  return self._db
75
 
76
  @property
test_startup.py CHANGED
@@ -30,6 +30,10 @@ def test_config():
30
  try:
31
  logger.info("Testing configuration...")
32
  from config import get_settings
 
 
 
 
33
  settings = get_settings()
34
  logger.info(f"LLM Model: {settings.llm_model}")
35
  logger.info(f"Embedding Model: {settings.embedding_model}")
@@ -45,11 +49,14 @@ def test_vector_store():
45
  try:
46
  logger.info("Testing vector store...")
47
  from config import get_settings
48
- from vector_store_client import VectorStoreClient
 
 
 
49
 
50
  settings = get_settings()
51
  client = VectorStoreClient(uri=settings.lancedb_uri)
52
- client.connect()
53
  count = client.count_documents()
54
  logger.info(f"Documents in database: {count}")
55
  client.close()
@@ -57,6 +64,8 @@ def test_vector_store():
57
  return True
58
  except Exception as e:
59
  logger.error(f"❌ Vector store failed: {e}")
 
 
60
  return False
61
 
62
  def test_embeddings():
@@ -78,20 +87,22 @@ def test_agent():
78
  """Test agent creation."""
79
  try:
80
  logger.info("Testing agent creation...")
81
- import asyncio
82
  from agent.a11y_agent import create_agent
 
 
 
83
 
84
- async def _test():
85
- agent = await create_agent()
86
- logger.info(f"Agent language: {agent.language}")
87
- logger.info(f"Agent model: {agent.model}")
88
- agent.close()
89
 
90
- asyncio.run(_test())
91
  logger.success("✅ Agent created successfully")
92
  return True
93
  except Exception as e:
94
  logger.error(f"❌ Agent creation failed: {e}")
 
 
95
  return False
96
 
97
  def main():
 
30
  try:
31
  logger.info("Testing configuration...")
32
  from config import get_settings
33
+ import os
34
+
35
+ os.environ.setdefault("OPENAI_API_KEY", "test-key-for-validation")
36
+
37
  settings = get_settings()
38
  logger.info(f"LLM Model: {settings.llm_model}")
39
  logger.info(f"Embedding Model: {settings.embedding_model}")
 
49
  try:
50
  logger.info("Testing vector store...")
51
  from config import get_settings
52
+ from database.vector_store_client import VectorStoreClient
53
+ import os
54
+
55
+ os.environ.setdefault("OPENAI_API_KEY", "test-key-for-validation")
56
 
57
  settings = get_settings()
58
  client = VectorStoreClient(uri=settings.lancedb_uri)
59
+
60
  count = client.count_documents()
61
  logger.info(f"Documents in database: {count}")
62
  client.close()
 
64
  return True
65
  except Exception as e:
66
  logger.error(f"❌ Vector store failed: {e}")
67
+ import traceback
68
+ logger.error(traceback.format_exc())
69
  return False
70
 
71
  def test_embeddings():
 
87
  """Test agent creation."""
88
  try:
89
  logger.info("Testing agent creation...")
 
90
  from agent.a11y_agent import create_agent
91
+ import os
92
+
93
+ os.environ.setdefault("OPENAI_API_KEY", "test-key-for-validation")
94
 
95
+ agent = create_agent()
96
+ logger.info(f"Agent language: {agent.language}")
97
+ logger.info(f"Agent model: {agent.model}")
98
+ agent.close()
 
99
 
 
100
  logger.success("✅ Agent created successfully")
101
  return True
102
  except Exception as e:
103
  logger.error(f"❌ Agent creation failed: {e}")
104
+ import traceback
105
+ logger.error(traceback.format_exc())
106
  return False
107
 
108
  def main():