File size: 8,152 Bytes
56fd21a
7299972
b88df70
ea4670b
0479845
 
af49a43
 
 
 
b88df70
68b95db
b88df70
68b95db
56fd21a
5855a4f
 
 
 
7299972
b88df70
8037dca
68b95db
0479845
 
 
 
 
d7d3aad
0479845
 
 
 
 
 
 
b88df70
0005aa0
 
b88df70
0005aa0
 
 
080d622
b88df70
 
 
c629e49
b88df70
0479845
 
 
2aa225e
b88df70
cd9e2f6
 
 
 
 
56fd21a
cd9e2f6
b88df70
d7d3aad
b88df70
5193d26
cd9e2f6
b88df70
 
cd9e2f6
 
 
b88df70
cd9e2f6
 
 
 
0e8391a
cd9e2f6
 
 
5193d26
b88df70
68b95db
d7d3aad
b88df70
 
 
 
68b95db
b88df70
ea4670b
54a2558
 
 
 
 
 
 
 
 
 
 
 
 
f4e115f
 
 
a070fd0
f4e115f
 
 
 
7d17621
54a2558
 
 
 
 
 
f4e115f
54a2558
 
 
 
 
f4e115f
 
54a2558
 
 
 
 
f4e115f
 
f4e11b9
 
 
 
b88df70
75ffb15
 
f4e11b9
e0b861a
 
f4e115f
68b95db
b88df70
1349452
 
f4e115f
 
1349452
f4e115f
 
 
 
 
1349452
 
f4e115f
 
1349452
 
 
 
 
 
 
 
 
 
 
 
68b95db
1349452
 
b88df70
1349452
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84f1cd4
2d58515
 
 
56fd21a
2d58515
 
 
f4e115f
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
import os
import sys
import threading
import time
import requests
from requests.exceptions import ConnectionError

os.environ['MPLCONFIGDIR'] = os.path.join(os.getcwd(), 'cache', 'matplotlib')
os.makedirs(os.environ['MPLCONFIGDIR'], exist_ok=True)

import gradio as gr
import uvicorn
from fastapi import FastAPI
from fastapi.responses import HTMLResponse

# Add project root to Python path
current_dir = os.path.abspath(os.path.dirname(__file__))
if current_dir not in sys.path:
    sys.path.insert(0, current_dir)

# Import our main application
from api.fastapi_server import app as fastapi_app

def wait_for_fastapi(timeout=30, interval=0.5):
    """Wait for FastAPI server to start"""
    start_time = time.time()
    while time.time() - start_time < timeout:
        try:
            response = requests.get("http://127.0.0.1:7860/health")
            if response.status_code == 200:
                print("FastAPI server is ready!")
                return True
        except ConnectionError:
            time.sleep(interval)
    return False

# Run FastAPI server in a separate thread
#def run_fastapi():
#    uvicorn.run(fastapi_app, host="0.0.0.0", port=7860)
def run_fastapi():
    import multiprocessing
    multiprocessing.Process(target=uvicorn.run, args=(fastapi_app,), kwargs={"host": "0.0.0.0", "port": 7860}).start()


# Start FastAPI in a background thread
fastapi_thread = threading.Thread(target=run_fastapi, daemon=True)
fastapi_thread.start()

# Wait for FastAPI to start
if not wait_for_fastapi():
    print("Failed to start FastAPI server")
    sys.exit(1)

# Create a Gradio interface that will proxy requests to FastAPI
def respond(message, history, conversation_id=None):
    """Handle chat messages and update conversation history"""
    if not message:
        return history, conversation_id
    
    try:
        # Send request to FastAPI backend
        response = requests.post(
            "http://127.0.0.1:7860/chat",
            json={"message": message, "conversation_id": conversation_id}
        )
        
        if response.status_code == 200:
            data = response.json()
            # Update conversation history
            history = history + [(message, data["response"])]
            return history, data["conversation_id"]
        else:
            error_message = f"Error: {response.status_code} - {response.text}"
            history = history + [(message, error_message)]
            return history, conversation_id
            
    except Exception as e:
        error_message = f"Error connecting to API: {str(e)}"
        history = history + [(message, error_message)]
        return history, conversation_id

def build_kb():
    try:
        response = requests.post("http://127.0.0.1:7860/build-kb")
        if response.status_code == 200:
            return f"Success: {response.json()['message']}"
        else:
            return f"Error: {response.status_code} - {response.text}"
    except Exception as e:
        return f"API connection error: {str(e)}"

def get_kb_size():
    """Calculate actual knowledge base size from files"""
    vector_store_path = "vector_store"
    try:
        total_size = 0
        for file in ["index.faiss", "index.pkl"]:
            file_path = os.path.join(vector_store_path, file)
            if os.path.exists(file_path):
                total_size += os.path.getsize(file_path)
        return total_size / (1024 * 1024)  # Convert to MB
    except Exception:
        return None

# Добавим функцию проверки статуса базы знаний
def check_kb_status():
    try:
        response = requests.get("http://127.0.0.1:7860/status")
        if response.status_code == 200:
            data = response.json()
            if data["knowledge_base_exists"]:
                kb_info = data["kb_info"]
                version = kb_info.get('version', 'N/A')
                
                # Получаем реальный размер файлов
                actual_size = get_kb_size()
                size_text = f"{actual_size:.2f} MB" if actual_size is not None else "N/A"
                
                return f"✅ База знаний готова к работе\nВерсия: {version}\nРазмер: {size_text}"
            else:
                # Проверяем, есть ли файлы на диске
                if os.path.exists(os.path.join("vector_store", "index.faiss")):
                    actual_size = get_kb_size()
                    size_text = f"{actual_size:.2f} MB" if actual_size is not None else "N/A"
                    return f"✅ База знаний найдена на диске\nРазмер: {size_text}\nТребуется перезагрузка сервера"
                return "❌ База знаний не создана. Нажмите кнопку 'Create/Update Knowledge Base'"
    except Exception as e:
        # Проверяем наличие файлов даже при ошибке соединения
        if os.path.exists(os.path.join("vector_store", "index.faiss")):
            actual_size = get_kb_size()
            size_text = f"{actual_size:.2f} MB" if actual_size is not None else "N/A"
            return f"⚠️ Ошибка соединения, но база знаний существует\nРазмер: {size_text}"
        return f"❌ Ошибка проверки статуса: {str(e)}"

def clear_history():
    """Reset chat history and conversation ID"""
    return [], None  # Returns empty history and resets conversation ID

# Create the Gradio interface
demo = gr.Blocks(title="Status Law Assistant", theme=gr.themes.Soft())
with demo:
    # Add conversation_id state first
    conversation_id = gr.State(None)
    
    gr.Markdown("# 🤖 Status Law Assistant")
    
    with gr.Row():
        # Left column for chat (larger)
        with gr.Column(scale=3):
            chatbot = gr.Chatbot(
                label="Conversation",
                height=600,
                show_label=False,
                bubble_full_width=False
            )
            with gr.Row():
                msg = gr.Textbox(
                    label="Enter your question here",
                    placeholder="Type your message and press Enter...",
                    scale=4
                )
                submit_btn = gr.Button("Send", variant="primary", scale=1)
        
        # Right column for controls (smaller)
        with gr.Column(scale=1):
            gr.Markdown("### Knowledge Base Controls")
            build_kb_btn = gr.Button("Create/Update Knowledge Base", variant="primary")
            check_status_btn = gr.Button("Check Status")
            kb_status = gr.Textbox(
                label="Knowledge Base Status",
                value="Checking status...",
                interactive=False
            )
            
            gr.Markdown("### Chat Controls")
            clear_btn = gr.Button("Clear Chat History")
            
            # Help section
            with gr.Accordion("ℹ️ How to use", open=False):
                gr.Markdown("""
                1. First, click **Create/Update Knowledge Base** button
                2. Wait for confirmation message
                3. Enter your question in the text field and press Enter or "Send" button
                4. Use "Clear Chat History" to start a new conversation
                """)
    
    # Event handlers remain the same
    msg.submit(respond, [msg, chatbot, conversation_id], [chatbot, conversation_id])
    submit_btn.click(respond, [msg, chatbot, conversation_id], [chatbot, conversation_id])
    clear_btn.click(clear_history, None, [chatbot, conversation_id])
    build_kb_btn.click(build_kb, inputs=None, outputs=kb_status)
    check_status_btn.click(check_kb_status, inputs=None, outputs=kb_status)

# Mount Gradio app to FastAPI at root path
app = gr.mount_gradio_app(fastapi_app, demo, path="/")

if __name__ == "__main__":
    # Launch the combined app
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860)
    #demo.launch(server_name="0.0.0.0", server_port=7860, share=False)