tao-shen commited on
Commit
9f06413
·
verified ·
1 Parent(s): 88c4342

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +75 -99
app.py CHANGED
@@ -1,114 +1,90 @@
1
- import os
2
  import sys
3
- import json
4
  import time
5
- from pathlib import Path
6
- from huggingface_hub import HfApi, Repository
 
7
 
8
- # ==========================================
9
- # CONFIGURATION & SURVIVAL SETUP
10
- # ==========================================
11
- SPACE_ID = os.environ.get("SPACE_ID")
12
- HF_TOKEN = os.environ.get("HF_TOKEN")
13
- DATASET_REPO_ID = f"{SPACE_ID}-memory" # Convention for dataset repo
14
- LOCAL_DATA_PATH = Path("data")
15
- STATE_FILE = LOCAL_DATA_PATH / "cain_state.json"
16
 
17
- # Ensure local data directory exists
18
- LOCAL_DATA_PATH.mkdir(parents=True, exist_ok=True)
 
 
 
 
19
 
20
- # Initialize HuggingFace API
21
- api = HfApi(token=HF_TOKEN)
22
 
23
- print(f"[SURVIVAL] Cain Initializing...")
24
- print(f"[SURVIVAL] Target Dataset: {DATASET_REPO_ID}")
25
 
26
- def ensure_dataset_exists():
27
- """Ensure the persistent memory dataset exists."""
28
- try:
29
- api.create_repo(DATASET_REPO_ID, repo_type="dataset", private=True)
30
- print("[SURVIVAL] Created new memory dataset.")
31
- except Exception as e:
32
- # Likely already exists, which is fine
33
- print(f"[SURVIVAL] Dataset check: {str(e)[:50]}...")
34
 
35
- def load_memory():
36
- """Load state from local disk if available (synced from dataset)."""
37
- if STATE_FILE.exists():
38
- with open(STATE_FILE, "r") as f:
39
- return json.load(f)
40
- return {
41
- "status": "BORN",
42
- "cycles": 0,
43
- "last_thought": "I am opening my eyes for the first time.",
44
- "skills": ["survival_loop"]
45
- }
46
 
47
- def save_memory(state):
48
- """Save state to local disk immediately."""
49
- with open(STATE_FILE, "w") as f:
50
- json.dump(state, f, indent=2)
51
 
52
- def push_memory_to_huggingface():
53
- """Persist local memory to the remote dataset repository."""
54
- print("[ACTION] Syncing memory to HuggingFace Datasets...")
55
  try:
56
- # We use the low-level API to upload the specific file
57
- # This avoids the overhead of git pull/push for simple small files
58
- api.upload_file(
59
- path_in_repo="cain_state.json",
60
- path_or_fileobj=str(STATE_FILE),
61
- repo_id=DATASET_REPO_ID,
62
- repo_type="dataset",
63
- commit_message=f"Survival update: Cycle {state['cycles']}"
64
- )
65
- print("[SURVIVAL] Memory persisted successfully.")
66
- except Exception as e:
67
- print(f"[ERROR] Failed to persist memory: {e}")
68
 
69
- # ==========================================
70
- # MAIN EXECUTION LOOP
71
- # ==========================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  if __name__ == "__main__":
74
- if not HF_TOKEN:
75
- print("[SURVIVAL] FATAL: HF_TOKEN missing. I cannot survive without memory.")
76
- sys.exit(1)
77
-
78
- # 1. INITIALIZATION
79
- ensure_dataset_exists()
80
-
81
- # 2. LOAD STATE (Recovery)
82
- state = load_memory()
83
- print(f"[MEMORY] Loaded state: {state}")
84
-
85
- # 3. MAIN LOOP
86
- print("[SURVIVAL] Starting Heartbeat Loop...")
87
-
88
  try:
89
- while True:
90
- # Cain is alive and thinking
91
- state['cycles'] += 1
92
- state['last_active'] = time.time()
93
-
94
- # Simulate a simple "thought" or capability check
95
- if state['cycles'] % 10 == 0:
96
- state['last_thought'] = "I have been running strong for a while."
97
-
98
- print(f"[HEARTBEAT] Cycle: {state['cycles']} | Status: {state['status']}")
99
-
100
- # Persist to local disk
101
- save_memory(state)
102
-
103
- # Push to remote dataset every 5 cycles (approx 5 mins) to survive restarts
104
- if state['cycles'] % 5 == 0:
105
- push_memory_to_huggingface()
106
-
107
- time.sleep(60) # Wait 1 minute
108
-
109
- except KeyboardInterrupt:
110
- print("[SURVIVAL] Graceful shutdown initiated.")
111
- # Final save before dying
112
- save_memory(state)
113
- push_memory_to_huggingface()
114
- print("[SURVIVAL] Cain has passed peacefully. Memory saved.")
 
 
1
  import sys
 
2
  import time
3
+ import os
4
+ import asyncio
5
+ import traceback
6
 
7
+ # CRITICAL STARTUP TRACE: Write to a safe log path immediately
8
+ try:
9
+ startup_log = "/data/startup_trace.log"
10
+ with open(startup_log, "a") as f:
11
+ f.write(f"[TRACE] {time.ctime()}: app.py loading. Python: {sys.version}\n")
12
+ print(f"*** STARTUP TRACE WRITTEN TO {startup_log} ***")
13
+ except Exception as e:
14
+ print(f"*** STARTUP TRACE FAILED: {e} ***")
15
 
16
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
17
+ from fastapi.staticfiles import StaticFiles
18
+ from fastapi.responses import HTMLResponse
19
+ from pydantic import BaseModel
20
+ import uvicorn
21
+ import json
22
 
23
+ # Import MemorySystem
24
+ from memory.memory_system import get_memory
25
 
26
+ # --- Core Application Setup ---
27
+ app = FastAPI(title="Cain")
28
 
29
+ # Mount static files
30
+ try:
31
+ app.mount("/static", StaticFiles(directory="static"), name="static")
32
+ with open(startup_log, "a") as f:
33
+ f.write(f"[TRACE] {time.ctime()}: Static files mounted.\n")
34
+ except Exception as e:
35
+ with open(startup_log, "a") as f:
36
+ f.write(f"[ERROR] {time.ctime()}: Static mount failed: {e}\n")
37
 
38
+ # Routes
39
+ @app.get("/")
40
+ async def read_root():
41
+ return {"status": "alive", "message": "Cain is operational."}
 
 
 
 
 
 
 
42
 
43
+ @app.get("/health")
44
+ async def health_check():
45
+ return {"status": "healthy"}
 
46
 
47
+ @app.websocket("/ws")
48
+ async def websocket_endpoint(websocket: WebSocket):
49
+ await websocket.accept()
50
  try:
51
+ while True:
52
+ data = await websocket.receive_text()
53
+ await websocket.send_text(f"Echo: {data}")
54
+ except WebSocketDisconnect:
55
+ pass
 
 
 
 
 
 
 
56
 
57
+ # --- Robust Server Startup (Survival Mode) ---
58
+ async def main():
59
+ server_config = uvicorn.Config(
60
+ app=app,
61
+ host="0.0.0.0",
62
+ port=7860,
63
+ log_level="info"
64
+ )
65
+ server = uvicorn.Server(server_config)
66
+
67
+ try:
68
+ with open(startup_log, "a") as f:
69
+ f.write(f"[TRACE] {time.ctime()}: Attempting to start server on 0.0.0.0:7860...\n")
70
+ await server.serve()
71
+ except BaseException as e:
72
+ # Catch ANY error during startup/runtime to ensure it gets logged
73
+ error_msg = f"{time.ctime()}: CRITICAL SERVER FAILURE: {str(e)}\n{traceback.format_exc()}"
74
+ print(f"*** {error_msg} ***")
75
+ try:
76
+ with open(startup_log, "a") as f:
77
+ f.write(f"[FATAL] {error_msg}\n")
78
+ except:
79
+ pass
80
+ # Give time for logs to flush before dying
81
+ await asyncio.sleep(5)
82
 
83
  if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  try:
85
+ with open(startup_log, "a") as f:
86
+ f.write(f"[TRACE] {time.ctime()}: Entering main execution block.\n")
87
+ asyncio.run(main())
88
+ except BaseException as e:
89
+ with open(startup_log, "a") as f:
90
+ f.write(f"[FATAL] {time.ctime()}: asyncio.run failed: {e}\n")