File size: 7,021 Bytes
d38c72c
b8e4c13
d38c72c
 
b8e4c13
 
d38c72c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6175abf
d38c72c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8e4c13
d38c72c
 
 
b8e4c13
d38c72c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8e4c13
d38c72c
 
b8e4c13
d38c72c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8e4c13
 
d38c72c
b8e4c13
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#!/usr/bin/env python3
"""
GAKR AI Chatbot - Startup Script
Handles environment setup and server startup
"""

import os
import sys
import subprocess
import argparse
import socket
from pathlib import Path

def configure_output_encoding():
    """Avoid UnicodeEncodeError on non-UTF terminal encodings."""
    try:
        if hasattr(sys.stdout, "reconfigure"):
            sys.stdout.reconfigure(encoding="utf-8", errors="replace")
        if hasattr(sys.stderr, "reconfigure"):
            sys.stderr.reconfigure(encoding="utf-8", errors="replace")
    except Exception:
        pass

def print_banner():
    """Print startup banner"""
    print("""
    +--------------------------------------------------------------+
    |                                                              |
    |                GAKR AI Chatbot Platform                      |
    |                                                              |
    |         Powered by NVIDIA API + Web Search                   |
    |                                                              |
    +--------------------------------------------------------------+
    """)

def check_python_version():
    """Check if Python version is compatible"""
    if sys.version_info < (3, 8):
        print("❌ Error: Python 3.8 or higher is required")
        print(f"   Current version: {sys.version_info.major}.{sys.version_info.minor}")
        return False
    print(f"✅ Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
    return True

def check_dependencies():
    """Check if required dependencies are installed"""
    backend_dir = Path(__file__).parent / "backend"
    req_file = backend_dir / "requirements.txt"
    
    if not req_file.exists():
        print("⚠️  requirements.txt not found")
        return False
    
    print("📦 Checking dependencies...")
    
    # Try to import key modules
    try:
        import fastapi
        print("   ✓ FastAPI")
    except ImportError:
        print("   ✗ FastAPI (not installed)")
        return False
    
    try:
        import httpx
        print("   ✓ httpx")
    except ImportError:
        print("   ✗ httpx (not installed)")
        return False

    try:
        import PyPDF2
        print("   ✓ PyPDF2")
    except ImportError:
        print("   ✗ PyPDF2 (not installed)")
        return False

    try:
        import docx  # noqa: F401
        print("   ✓ python-docx")
    except ImportError:
        print("   ✗ python-docx (not installed)")
        return False

    try:
        from PIL import Image  # noqa: F401
        print("   ✓ Pillow")
    except ImportError:
        print("   ✗ Pillow (not installed)")
        return False

    try:
        import openpyxl  # noqa: F401
        print("   ✓ openpyxl")
    except ImportError:
        print("   ✗ openpyxl (not installed)")
        return False

    try:
        import xlrd  # noqa: F401
        print("   ✓ xlrd")
    except ImportError:
        print("   ⚠️ xlrd (not installed, legacy .xls parsing disabled)")

    try:
        import pytesseract
        try:
            pytesseract.get_tesseract_version()
            print("   ✓ pytesseract + Tesseract OCR")
        except Exception:
            print("   ⚠️ pytesseract installed, but Tesseract OCR binary not detected")
    except ImportError:
        print("   ⚠️ pytesseract (not installed, image OCR disabled)")
    except Exception as e:
        print(f"   ⚠️ pytesseract unavailable ({type(e).__name__}: {e})")
        print("      Image OCR disabled; server will continue without OCR.")

    return True

def setup_directories():
    """Create necessary directories"""
    base_dir = Path(__file__).parent
    
    dirs = [
        base_dir / "data",
        base_dir / "data" / "uploads"
    ]
    
    for d in dirs:
        d.mkdir(parents=True, exist_ok=True)
    
    print("✅ Directories initialized")

def is_port_available(host, port):
    """Check whether a TCP port is available for binding"""
    bind_host = host if host and host != "0.0.0.0" else "0.0.0.0"
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            sock.bind((bind_host, int(port)))
            return True
        except OSError:
            return False

def find_available_port(host, start_port, max_tries=50):
    """Find first available port starting from start_port"""
    port = int(start_port)
    for _ in range(max_tries):
        if is_port_available(host, port):
            return port
        port += 1
    return None

def start_server(host, port, reload):
    """Start the FastAPI server"""
    backend_dir = Path(__file__).parent / "backend"

    requested_port = int(port)
    selected_port = find_available_port(host, requested_port)
    if selected_port is None:
        print(f"\n❌ No available port found from {requested_port} to {requested_port + 49}")
        print("   Stop existing server processes or pass a different --port value.")
        return 1

    if selected_port != requested_port:
        print(f"\n⚠️  Port {requested_port} is already in use. Switching to port {selected_port}.")
        port = selected_port

    print(f"\n🚀 Starting server on http://{host}:{port}")
    print("   Press Ctrl+C to stop\n")
    
    cmd = [
        sys.executable, "-m", "uvicorn",
        "main:app",
        "--host", host,
        "--port", str(port),
    ]
    
    if reload:
        cmd.append("--reload")
    
    try:
        result = subprocess.run(cmd, cwd=backend_dir)
        return result.returncode
    except KeyboardInterrupt:
        print("\n\n👋 Server stopped")
        return 0

def main():
    configure_output_encoding()

    parser = argparse.ArgumentParser(description="GAKR AI Chatbot Server")
    default_port = int(os.getenv("PORT", "7860"))
    parser.add_argument("--host", default="0.0.0.0", help="Host to bind (default: 0.0.0.0)")
    parser.add_argument("--port", type=int, default=default_port, help=f"Port to run on (default: {default_port})")
    parser.add_argument("--reload", action="store_true", help="Enable auto-reload for development")
    parser.add_argument("--skip-checks", action="store_true", help="Skip dependency checks")
    
    args = parser.parse_args()
    
    print_banner()
    
    # Check Python version
    if not check_python_version():
        sys.exit(1)
    
    # Setup directories
    setup_directories()
    
    # Check dependencies
    if not args.skip_checks:
        if not check_dependencies():
            print("\n❌ Please install dependencies first:")
            print("   pip install -r backend/requirements.txt")
            sys.exit(1)
    
    # Start server
    exit_code = start_server(args.host, args.port, args.reload)
    if exit_code != 0:
        sys.exit(exit_code)

if __name__ == "__main__":
    main()