Commit
Β·
294dd7e
1
Parent(s):
47d523d
updated app.py
Browse files
app.py
CHANGED
|
@@ -6,14 +6,13 @@ from crewai_tools import SerperDevTool
|
|
| 6 |
from typing import List, Tuple
|
| 7 |
import time
|
| 8 |
|
| 9 |
-
# Environment variables setup
|
| 10 |
OPENROUTER_API_KEY = "your api key"
|
| 11 |
SERPER_API_KEY = "your api key"
|
| 12 |
|
| 13 |
-
|
| 14 |
os.environ["SERPER_API_KEY"] = SERPER_API_KEY
|
| 15 |
|
| 16 |
-
|
| 17 |
crew_llm = LLM(
|
| 18 |
model="openrouter/deepseek/deepseek-r1",
|
| 19 |
base_url="https://openrouter.ai/api/v1",
|
|
@@ -21,7 +20,7 @@ crew_llm = LLM(
|
|
| 21 |
temperature=0.7
|
| 22 |
)
|
| 23 |
|
| 24 |
-
|
| 25 |
direct_llm = ChatOpenAI(
|
| 26 |
model="deepseek/deepseek-r1",
|
| 27 |
openai_api_key=OPENROUTER_API_KEY,
|
|
@@ -32,14 +31,14 @@ direct_llm = ChatOpenAI(
|
|
| 32 |
|
| 33 |
class ConstructionChatbot:
|
| 34 |
def __init__(self):
|
| 35 |
-
self.memory: List[Tuple[str, str]] = []
|
| 36 |
self.setup_tools()
|
| 37 |
self.setup_crew()
|
| 38 |
|
| 39 |
def setup_tools(self):
|
| 40 |
"""Set up web search tools"""
|
| 41 |
try:
|
| 42 |
-
self.search_tool = SerperDevTool()
|
| 43 |
print("β
Web search tool initialized successfully")
|
| 44 |
except Exception as e:
|
| 45 |
self.search_tool = None
|
|
@@ -52,7 +51,7 @@ class ConstructionChatbot:
|
|
| 52 |
if self.search_tool:
|
| 53 |
tools.append(self.search_tool)
|
| 54 |
|
| 55 |
-
|
| 56 |
self.construction_agent = Agent(
|
| 57 |
role='Construction Expert Assistant',
|
| 58 |
goal='Provide accurate construction-related information ONLY. Reject all non-construction queries.',
|
|
@@ -80,7 +79,7 @@ class ConstructionChatbot:
|
|
| 80 |
max_execution_time=45
|
| 81 |
)
|
| 82 |
|
| 83 |
-
|
| 84 |
if self.search_tool:
|
| 85 |
self.research_agent = Agent(
|
| 86 |
role='Construction Research Specialist',
|
|
@@ -109,7 +108,7 @@ class ConstructionChatbot:
|
|
| 109 |
"""Add interaction to rolling memory window"""
|
| 110 |
self.memory.append((user_query, response))
|
| 111 |
if len(self.memory) > 5:
|
| 112 |
-
self.memory.pop(0)
|
| 113 |
|
| 114 |
def get_chat_history(self) -> str:
|
| 115 |
"""Format chat history for prompt"""
|
|
@@ -136,7 +135,7 @@ class ConstructionChatbot:
|
|
| 136 |
|
| 137 |
def generate_response_with_crew(self, user_query: str) -> str:
|
| 138 |
"""Generate response using CrewAI with web search capabilities"""
|
| 139 |
-
|
| 140 |
if not self.is_construction_related(user_query):
|
| 141 |
response = "I can only assist with construction-related queries. Please ask about building, safety, materials, project management, or engineering topics."
|
| 142 |
self.add_to_memory(user_query, response)
|
|
@@ -145,12 +144,12 @@ class ConstructionChatbot:
|
|
| 145 |
chat_history = self.get_chat_history()
|
| 146 |
|
| 147 |
try:
|
| 148 |
-
|
| 149 |
search_keywords = ['current', 'latest', 'recent', 'today', '2024', '2025', 'price', 'cost', 'regulation', 'new', 'trend']
|
| 150 |
needs_search = any(keyword in user_query.lower() for keyword in search_keywords)
|
| 151 |
|
| 152 |
if needs_search and self.research_agent:
|
| 153 |
-
|
| 154 |
research_task = Task(
|
| 155 |
description=f"""Search for current construction-related information about: {user_query}
|
| 156 |
|
|
@@ -167,7 +166,7 @@ class ConstructionChatbot:
|
|
| 167 |
agent=self.research_agent
|
| 168 |
)
|
| 169 |
|
| 170 |
-
|
| 171 |
response_task = Task(
|
| 172 |
description=f"""Based on research findings and chat history, provide a comprehensive response to: {user_query}
|
| 173 |
|
|
@@ -185,15 +184,15 @@ class ConstructionChatbot:
|
|
| 185 |
context=[research_task]
|
| 186 |
)
|
| 187 |
|
| 188 |
-
|
| 189 |
crew = Crew(
|
| 190 |
agents=[self.research_agent, self.construction_agent],
|
| 191 |
tasks=[research_task, response_task],
|
| 192 |
-
verbose=False
|
| 193 |
)
|
| 194 |
|
| 195 |
else:
|
| 196 |
-
|
| 197 |
response_task = Task(
|
| 198 |
description=f"""Provide expert construction advice for: {user_query}
|
| 199 |
|
|
@@ -210,28 +209,28 @@ class ConstructionChatbot:
|
|
| 210 |
agent=self.construction_agent
|
| 211 |
)
|
| 212 |
|
| 213 |
-
|
| 214 |
crew = Crew(
|
| 215 |
agents=[self.construction_agent],
|
| 216 |
tasks=[response_task],
|
| 217 |
verbose=False
|
| 218 |
)
|
| 219 |
|
| 220 |
-
|
| 221 |
result = crew.kickoff()
|
| 222 |
response = str(result).strip()
|
| 223 |
|
| 224 |
-
|
| 225 |
if not response or len(response) < 10:
|
| 226 |
response = "I apologize, but I'm having trouble generating a proper response. Could you please rephrase your construction-related question?"
|
| 227 |
|
| 228 |
-
|
| 229 |
self.add_to_memory(user_query, response)
|
| 230 |
return response
|
| 231 |
|
| 232 |
except Exception as e:
|
| 233 |
print(f"CrewAI Error: {e}")
|
| 234 |
-
|
| 235 |
return self.generate_response_direct(user_query)
|
| 236 |
|
| 237 |
def generate_response_direct(self, user_query: str) -> str:
|
|
@@ -279,10 +278,9 @@ Technical error: {str(e)[:100]}..."""
|
|
| 279 |
print(f"Crew method failed, using direct method: {e}")
|
| 280 |
return self.generate_response_direct(user_query)
|
| 281 |
|
| 282 |
-
|
| 283 |
chatbot = ConstructionChatbot()
|
| 284 |
|
| 285 |
-
# Custom CSS for construction-themed interface with vibrant colors
|
| 286 |
custom_css = """
|
| 287 |
/* Construction-themed color palette */
|
| 288 |
:root {
|
|
@@ -602,7 +600,7 @@ def create_interface():
|
|
| 602 |
|
| 603 |
with gr.Blocks(css=custom_css, title="ποΈ Construction AI Assistant - DeepSeek R1 ποΈ") as interface:
|
| 604 |
|
| 605 |
-
|
| 606 |
gr.HTML("""
|
| 607 |
<div class="construction-header">
|
| 608 |
ποΈ CONSTRUCTION COMPANY AI ASSISTANT ποΈ
|
|
@@ -613,7 +611,7 @@ def create_interface():
|
|
| 613 |
</div>
|
| 614 |
""")
|
| 615 |
|
| 616 |
-
|
| 617 |
def get_status_info():
|
| 618 |
search_status = "π Web Search: ONLINE" if chatbot.search_tool else "π Web Search: OFFLINE"
|
| 619 |
search_class = "status-online" if chatbot.search_tool else "status-offline"
|
|
@@ -633,7 +631,7 @@ def create_interface():
|
|
| 633 |
|
| 634 |
memory_status = gr.HTML(get_status_info())
|
| 635 |
|
| 636 |
-
|
| 637 |
with gr.Row():
|
| 638 |
with gr.Column():
|
| 639 |
chatbot_interface = gr.Chatbot(
|
|
@@ -648,7 +646,7 @@ def create_interface():
|
|
| 648 |
elem_classes=["chatbot"]
|
| 649 |
)
|
| 650 |
|
| 651 |
-
|
| 652 |
with gr.Row():
|
| 653 |
with gr.Column(scale=8):
|
| 654 |
msg_input = gr.Textbox(
|
|
@@ -667,14 +665,14 @@ def create_interface():
|
|
| 667 |
elem_classes=["btn-primary"]
|
| 668 |
)
|
| 669 |
|
| 670 |
-
|
| 671 |
with gr.Row():
|
| 672 |
with gr.Column(scale=1):
|
| 673 |
clear_btn = gr.Button("ποΈ Clear Chat", variant="secondary", elem_classes=["btn-secondary"])
|
| 674 |
with gr.Column(scale=1):
|
| 675 |
examples_btn = gr.Button("π‘ Examples", variant="secondary", elem_classes=["btn-secondary"])
|
| 676 |
|
| 677 |
-
|
| 678 |
examples_html = f"""
|
| 679 |
<div class="success-box">
|
| 680 |
<h4>β
CONSTRUCTION QUESTIONS I CAN ANSWER {'(with Live Web Search!)' if chatbot.search_tool else ''}:</h4>
|
|
@@ -713,7 +711,7 @@ def create_interface():
|
|
| 713 |
|
| 714 |
examples_display = gr.HTML(examples_html, visible=False)
|
| 715 |
|
| 716 |
-
|
| 717 |
def update_memory_display():
|
| 718 |
return get_status_info()
|
| 719 |
|
|
@@ -721,14 +719,14 @@ def create_interface():
|
|
| 721 |
if not message.strip():
|
| 722 |
return history, "", update_memory_display()
|
| 723 |
|
| 724 |
-
|
| 725 |
if history is None:
|
| 726 |
history = []
|
| 727 |
|
| 728 |
-
|
| 729 |
history.append({"role": "user", "content": message})
|
| 730 |
|
| 731 |
-
|
| 732 |
try:
|
| 733 |
response = chatbot.generate_response(message)
|
| 734 |
history.append({"role": "assistant", "content": response})
|
|
@@ -745,13 +743,13 @@ def create_interface():
|
|
| 745 |
def toggle_examples(current_visibility):
|
| 746 |
return not current_visibility
|
| 747 |
|
| 748 |
-
|
| 749 |
msg_input.submit(respond, [msg_input, chatbot_interface], [chatbot_interface, msg_input, memory_status])
|
| 750 |
send_btn.click(respond, [msg_input, chatbot_interface], [chatbot_interface, msg_input, memory_status])
|
| 751 |
clear_btn.click(clear_chat, outputs=[chatbot_interface, memory_status])
|
| 752 |
examples_btn.click(toggle_examples, inputs=examples_display, outputs=examples_display)
|
| 753 |
|
| 754 |
-
|
| 755 |
if chatbot.search_tool:
|
| 756 |
gr.HTML(f"""
|
| 757 |
<div class="success-box">
|
|
@@ -784,7 +782,7 @@ def create_interface():
|
|
| 784 |
</div>
|
| 785 |
""")
|
| 786 |
|
| 787 |
-
|
| 788 |
gr.HTML(f"""
|
| 789 |
<div class="info-box">
|
| 790 |
<h4>π§ POWERED BY DEEPSEEK R1 - ADVANCED REASONING AI</h4>
|
|
@@ -820,7 +818,7 @@ def create_interface():
|
|
| 820 |
</div>
|
| 821 |
""")
|
| 822 |
|
| 823 |
-
|
| 824 |
gr.HTML("""
|
| 825 |
<div style="text-align: center; margin-top: 30px; padding: 20px; background: linear-gradient(135deg, rgba(255, 107, 26, 0.1), rgba(255, 193, 7, 0.1)); border-radius: 15px; border: 2px solid var(--construction-orange);">
|
| 826 |
<h5 style="color: var(--construction-orange); margin-bottom: 10px;">ποΈ PROFESSIONAL CONSTRUCTION AI ASSISTANT ποΈ</h5>
|
|
@@ -834,7 +832,7 @@ def create_interface():
|
|
| 834 |
|
| 835 |
return interface
|
| 836 |
|
| 837 |
-
|
| 838 |
if __name__ == "__main__":
|
| 839 |
print("ποΈ" + "="*80)
|
| 840 |
print("ποΈ STARTING CONSTRUCTION COMPANY AI ASSISTANT")
|
|
@@ -850,7 +848,7 @@ if __name__ == "__main__":
|
|
| 850 |
print("ποΈ" + "="*80)
|
| 851 |
print("π Launching interface...")
|
| 852 |
|
| 853 |
-
|
| 854 |
if chatbot.search_tool:
|
| 855 |
print("β
Web search tool initialized successfully!")
|
| 856 |
print("π‘ Users can get real-time construction data")
|
|
@@ -860,10 +858,10 @@ if __name__ == "__main__":
|
|
| 860 |
|
| 861 |
print("ποΈ" + "="*80)
|
| 862 |
|
| 863 |
-
|
| 864 |
interface = create_interface()
|
| 865 |
interface.launch(
|
| 866 |
-
share=
|
| 867 |
server_name="0.0.0.0",
|
| 868 |
server_port=7863,
|
| 869 |
show_error=True,
|
|
|
|
| 6 |
from typing import List, Tuple
|
| 7 |
import time
|
| 8 |
|
|
|
|
| 9 |
OPENROUTER_API_KEY = "your api key"
|
| 10 |
SERPER_API_KEY = "your api key"
|
| 11 |
|
| 12 |
+
|
| 13 |
os.environ["SERPER_API_KEY"] = SERPER_API_KEY
|
| 14 |
|
| 15 |
+
|
| 16 |
crew_llm = LLM(
|
| 17 |
model="openrouter/deepseek/deepseek-r1",
|
| 18 |
base_url="https://openrouter.ai/api/v1",
|
|
|
|
| 20 |
temperature=0.7
|
| 21 |
)
|
| 22 |
|
| 23 |
+
|
| 24 |
direct_llm = ChatOpenAI(
|
| 25 |
model="deepseek/deepseek-r1",
|
| 26 |
openai_api_key=OPENROUTER_API_KEY,
|
|
|
|
| 31 |
|
| 32 |
class ConstructionChatbot:
|
| 33 |
def __init__(self):
|
| 34 |
+
self.memory: List[Tuple[str, str]] = []
|
| 35 |
self.setup_tools()
|
| 36 |
self.setup_crew()
|
| 37 |
|
| 38 |
def setup_tools(self):
|
| 39 |
"""Set up web search tools"""
|
| 40 |
try:
|
| 41 |
+
self.search_tool = SerperDevTool()
|
| 42 |
print("β
Web search tool initialized successfully")
|
| 43 |
except Exception as e:
|
| 44 |
self.search_tool = None
|
|
|
|
| 51 |
if self.search_tool:
|
| 52 |
tools.append(self.search_tool)
|
| 53 |
|
| 54 |
+
|
| 55 |
self.construction_agent = Agent(
|
| 56 |
role='Construction Expert Assistant',
|
| 57 |
goal='Provide accurate construction-related information ONLY. Reject all non-construction queries.',
|
|
|
|
| 79 |
max_execution_time=45
|
| 80 |
)
|
| 81 |
|
| 82 |
+
|
| 83 |
if self.search_tool:
|
| 84 |
self.research_agent = Agent(
|
| 85 |
role='Construction Research Specialist',
|
|
|
|
| 108 |
"""Add interaction to rolling memory window"""
|
| 109 |
self.memory.append((user_query, response))
|
| 110 |
if len(self.memory) > 5:
|
| 111 |
+
self.memory.pop(0)
|
| 112 |
|
| 113 |
def get_chat_history(self) -> str:
|
| 114 |
"""Format chat history for prompt"""
|
|
|
|
| 135 |
|
| 136 |
def generate_response_with_crew(self, user_query: str) -> str:
|
| 137 |
"""Generate response using CrewAI with web search capabilities"""
|
| 138 |
+
|
| 139 |
if not self.is_construction_related(user_query):
|
| 140 |
response = "I can only assist with construction-related queries. Please ask about building, safety, materials, project management, or engineering topics."
|
| 141 |
self.add_to_memory(user_query, response)
|
|
|
|
| 144 |
chat_history = self.get_chat_history()
|
| 145 |
|
| 146 |
try:
|
| 147 |
+
|
| 148 |
search_keywords = ['current', 'latest', 'recent', 'today', '2024', '2025', 'price', 'cost', 'regulation', 'new', 'trend']
|
| 149 |
needs_search = any(keyword in user_query.lower() for keyword in search_keywords)
|
| 150 |
|
| 151 |
if needs_search and self.research_agent:
|
| 152 |
+
|
| 153 |
research_task = Task(
|
| 154 |
description=f"""Search for current construction-related information about: {user_query}
|
| 155 |
|
|
|
|
| 166 |
agent=self.research_agent
|
| 167 |
)
|
| 168 |
|
| 169 |
+
|
| 170 |
response_task = Task(
|
| 171 |
description=f"""Based on research findings and chat history, provide a comprehensive response to: {user_query}
|
| 172 |
|
|
|
|
| 184 |
context=[research_task]
|
| 185 |
)
|
| 186 |
|
| 187 |
+
|
| 188 |
crew = Crew(
|
| 189 |
agents=[self.research_agent, self.construction_agent],
|
| 190 |
tasks=[research_task, response_task],
|
| 191 |
+
verbose=False
|
| 192 |
)
|
| 193 |
|
| 194 |
else:
|
| 195 |
+
|
| 196 |
response_task = Task(
|
| 197 |
description=f"""Provide expert construction advice for: {user_query}
|
| 198 |
|
|
|
|
| 209 |
agent=self.construction_agent
|
| 210 |
)
|
| 211 |
|
| 212 |
+
|
| 213 |
crew = Crew(
|
| 214 |
agents=[self.construction_agent],
|
| 215 |
tasks=[response_task],
|
| 216 |
verbose=False
|
| 217 |
)
|
| 218 |
|
| 219 |
+
|
| 220 |
result = crew.kickoff()
|
| 221 |
response = str(result).strip()
|
| 222 |
|
| 223 |
+
|
| 224 |
if not response or len(response) < 10:
|
| 225 |
response = "I apologize, but I'm having trouble generating a proper response. Could you please rephrase your construction-related question?"
|
| 226 |
|
| 227 |
+
|
| 228 |
self.add_to_memory(user_query, response)
|
| 229 |
return response
|
| 230 |
|
| 231 |
except Exception as e:
|
| 232 |
print(f"CrewAI Error: {e}")
|
| 233 |
+
|
| 234 |
return self.generate_response_direct(user_query)
|
| 235 |
|
| 236 |
def generate_response_direct(self, user_query: str) -> str:
|
|
|
|
| 278 |
print(f"Crew method failed, using direct method: {e}")
|
| 279 |
return self.generate_response_direct(user_query)
|
| 280 |
|
| 281 |
+
|
| 282 |
chatbot = ConstructionChatbot()
|
| 283 |
|
|
|
|
| 284 |
custom_css = """
|
| 285 |
/* Construction-themed color palette */
|
| 286 |
:root {
|
|
|
|
| 600 |
|
| 601 |
with gr.Blocks(css=custom_css, title="ποΈ Construction AI Assistant - DeepSeek R1 ποΈ") as interface:
|
| 602 |
|
| 603 |
+
|
| 604 |
gr.HTML("""
|
| 605 |
<div class="construction-header">
|
| 606 |
ποΈ CONSTRUCTION COMPANY AI ASSISTANT ποΈ
|
|
|
|
| 611 |
</div>
|
| 612 |
""")
|
| 613 |
|
| 614 |
+
|
| 615 |
def get_status_info():
|
| 616 |
search_status = "π Web Search: ONLINE" if chatbot.search_tool else "π Web Search: OFFLINE"
|
| 617 |
search_class = "status-online" if chatbot.search_tool else "status-offline"
|
|
|
|
| 631 |
|
| 632 |
memory_status = gr.HTML(get_status_info())
|
| 633 |
|
| 634 |
+
|
| 635 |
with gr.Row():
|
| 636 |
with gr.Column():
|
| 637 |
chatbot_interface = gr.Chatbot(
|
|
|
|
| 646 |
elem_classes=["chatbot"]
|
| 647 |
)
|
| 648 |
|
| 649 |
+
|
| 650 |
with gr.Row():
|
| 651 |
with gr.Column(scale=8):
|
| 652 |
msg_input = gr.Textbox(
|
|
|
|
| 665 |
elem_classes=["btn-primary"]
|
| 666 |
)
|
| 667 |
|
| 668 |
+
|
| 669 |
with gr.Row():
|
| 670 |
with gr.Column(scale=1):
|
| 671 |
clear_btn = gr.Button("ποΈ Clear Chat", variant="secondary", elem_classes=["btn-secondary"])
|
| 672 |
with gr.Column(scale=1):
|
| 673 |
examples_btn = gr.Button("π‘ Examples", variant="secondary", elem_classes=["btn-secondary"])
|
| 674 |
|
| 675 |
+
|
| 676 |
examples_html = f"""
|
| 677 |
<div class="success-box">
|
| 678 |
<h4>β
CONSTRUCTION QUESTIONS I CAN ANSWER {'(with Live Web Search!)' if chatbot.search_tool else ''}:</h4>
|
|
|
|
| 711 |
|
| 712 |
examples_display = gr.HTML(examples_html, visible=False)
|
| 713 |
|
| 714 |
+
|
| 715 |
def update_memory_display():
|
| 716 |
return get_status_info()
|
| 717 |
|
|
|
|
| 719 |
if not message.strip():
|
| 720 |
return history, "", update_memory_display()
|
| 721 |
|
| 722 |
+
|
| 723 |
if history is None:
|
| 724 |
history = []
|
| 725 |
|
| 726 |
+
|
| 727 |
history.append({"role": "user", "content": message})
|
| 728 |
|
| 729 |
+
|
| 730 |
try:
|
| 731 |
response = chatbot.generate_response(message)
|
| 732 |
history.append({"role": "assistant", "content": response})
|
|
|
|
| 743 |
def toggle_examples(current_visibility):
|
| 744 |
return not current_visibility
|
| 745 |
|
| 746 |
+
|
| 747 |
msg_input.submit(respond, [msg_input, chatbot_interface], [chatbot_interface, msg_input, memory_status])
|
| 748 |
send_btn.click(respond, [msg_input, chatbot_interface], [chatbot_interface, msg_input, memory_status])
|
| 749 |
clear_btn.click(clear_chat, outputs=[chatbot_interface, memory_status])
|
| 750 |
examples_btn.click(toggle_examples, inputs=examples_display, outputs=examples_display)
|
| 751 |
|
| 752 |
+
|
| 753 |
if chatbot.search_tool:
|
| 754 |
gr.HTML(f"""
|
| 755 |
<div class="success-box">
|
|
|
|
| 782 |
</div>
|
| 783 |
""")
|
| 784 |
|
| 785 |
+
|
| 786 |
gr.HTML(f"""
|
| 787 |
<div class="info-box">
|
| 788 |
<h4>π§ POWERED BY DEEPSEEK R1 - ADVANCED REASONING AI</h4>
|
|
|
|
| 818 |
</div>
|
| 819 |
""")
|
| 820 |
|
| 821 |
+
|
| 822 |
gr.HTML("""
|
| 823 |
<div style="text-align: center; margin-top: 30px; padding: 20px; background: linear-gradient(135deg, rgba(255, 107, 26, 0.1), rgba(255, 193, 7, 0.1)); border-radius: 15px; border: 2px solid var(--construction-orange);">
|
| 824 |
<h5 style="color: var(--construction-orange); margin-bottom: 10px;">ποΈ PROFESSIONAL CONSTRUCTION AI ASSISTANT ποΈ</h5>
|
|
|
|
| 832 |
|
| 833 |
return interface
|
| 834 |
|
| 835 |
+
|
| 836 |
if __name__ == "__main__":
|
| 837 |
print("ποΈ" + "="*80)
|
| 838 |
print("ποΈ STARTING CONSTRUCTION COMPANY AI ASSISTANT")
|
|
|
|
| 848 |
print("ποΈ" + "="*80)
|
| 849 |
print("π Launching interface...")
|
| 850 |
|
| 851 |
+
|
| 852 |
if chatbot.search_tool:
|
| 853 |
print("β
Web search tool initialized successfully!")
|
| 854 |
print("π‘ Users can get real-time construction data")
|
|
|
|
| 858 |
|
| 859 |
print("ποΈ" + "="*80)
|
| 860 |
|
| 861 |
+
|
| 862 |
interface = create_interface()
|
| 863 |
interface.launch(
|
| 864 |
+
share=False,
|
| 865 |
server_name="0.0.0.0",
|
| 866 |
server_port=7863,
|
| 867 |
show_error=True,
|