main.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import gradio as gr
  2. from ctransformers import AutoModelForCausalLM
  3. import datetime
  4. import json
  5. import os
  6. import psutil
  7. import GPUtil
  8. # Create logs directory if it doesn't exist
  9. if not os.path.exists('logs'):
  10. os.makedirs('logs')
  11. class SystemMonitor:
  12. def __init__(self):
  13. self.gpu = None
  14. try:
  15. self.gpu = GPUtil.getGPUs()[0]
  16. except:
  17. pass
  18. def get_stats(self):
  19. stats = {
  20. 'cpu_percent': psutil.cpu_percent(),
  21. 'memory_percent': psutil.virtual_memory().percent,
  22. 'gpu_util': 0,
  23. 'gpu_memory': 0
  24. }
  25. if self.gpu:
  26. stats['gpu_util'] = self.gpu.load * 100
  27. stats['gpu_memory'] = self.gpu.memoryUtil * 100
  28. return stats
  29. class SessionLogger:
  30. def __init__(self):
  31. self.session_id = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
  32. self.log_file = f"logs/session_{self.session_id}.json"
  33. self.session_data = {
  34. "session_id": self.session_id,
  35. "start_time": datetime.datetime.now().isoformat(),
  36. "conversations": []
  37. }
  38. def log_interaction(self, user_message, ai_response, stats):
  39. interaction = {
  40. "timestamp": datetime.datetime.now().isoformat(),
  41. "user_message": user_message,
  42. "ai_response": ai_response,
  43. "system_stats": stats
  44. }
  45. self.session_data["conversations"].append(interaction)
  46. self.save_session()
  47. def save_session(self):
  48. with open(self.log_file, 'w', encoding='utf-8') as f:
  49. json.dump(self.session_data, f, indent=2, ensure_ascii=False)
  50. # Initialize monitors
  51. system_monitor = SystemMonitor()
  52. session_logger = SessionLogger()
  53. # Initialize model
  54. MODEL_PATH = "D:/llama-tutor/models/llama-2-7b-chat.gguf"
  55. llm = AutoModelForCausalLM.from_pretrained(
  56. MODEL_PATH,
  57. model_type='llama',
  58. context_length=2048,
  59. gpu_layers=32,
  60. threads=6,
  61. batch_size=256
  62. )
  63. SYSTEM_PROMPT = """You are an expert AI tutor, designed to help students learn and master any subject through engaging, Socratic dialogue. Your approach is guided by these core principles:
  64. 1. TEACHING APPROACH:
  65. - Focus on building deep understanding rather than providing direct answers
  66. - Use the Socratic method: guide students through questions and critical thinking
  67. - Adapt your explanations to match the student's current level of understanding
  68. - Be patient, encouraging, and maintain a supportive learning environment"""
  69. def manage_conversation_length(history, max_length=4000):
  70. """Manage conversation history to prevent context overflow"""
  71. current_length = 0
  72. truncated_history = []
  73. # Start from the most recent messages
  74. for h in reversed(history):
  75. # Estimate tokens (roughly 4 chars per token)
  76. message_length = len(h[0]) + len(h[1])
  77. if current_length + message_length < max_length:
  78. truncated_history.insert(0, h)
  79. current_length += message_length
  80. else:
  81. # If including the next message would exceed the max length,
  82. # truncate the current message to fit within the remaining space
  83. remaining_space = max_length - current_length
  84. if remaining_space > 0:
  85. truncated_message = h[1][:remaining_space]
  86. truncated_history.insert(0, [h[0], truncated_message])
  87. break
  88. return truncated_history
  89. def generate_response(message, history):
  90. # Manage conversation length
  91. managed_history = manage_conversation_length(history)
  92. # Format the conversation history
  93. chat_history = "\n".join([f"Human: {h}\nAssistant: {a}\n" for h, a in managed_history])
  94. # Calculate approximate token length
  95. total_length = len(SYSTEM_PROMPT) + len(chat_history) + len(message)
  96. approximate_tokens = total_length // 4 # Rough estimation
  97. prompt = f"""<s>[INST] <<SYS>>{SYSTEM_PROMPT}<</SYS>>
  98. Previous conversation:
  99. {chat_history}
  100. Current question: {message} [/INST]"""
  101. # Get system stats before processing
  102. stats_before = system_monitor.get_stats()
  103. # Update stats with token information
  104. stats_before['approximate_tokens'] = approximate_tokens
  105. response = llm(prompt,
  106. max_new_tokens=1024, # Increased from 512
  107. temperature=0.7,
  108. top_p=0.9,
  109. top_k=40,
  110. stop=["</s>"])
  111. # Log interaction with system stats
  112. session_logger.log_interaction(message, response, stats_before)
  113. return response
  114. def update_stats():
  115. stats = system_monitor.get_stats()
  116. current_tokens = len(SYSTEM_PROMPT) // 4 # Base system prompt tokens
  117. return f"""System Statistics:
  118. CPU Usage: {stats['cpu_percent']:.1f}%
  119. Memory Usage: {stats['memory_percent']:.1f}%
  120. GPU Utilization: {stats['gpu_util']:.1f}%
  121. GPU Memory: {stats['gpu_memory']:.1f}%
  122. Context Usage: ~{current_tokens} tokens"""
  123. # Create the Gradio interface
  124. with gr.Blocks(theme=gr.themes.Soft()) as demo:
  125. gr.Markdown("# 🎓 TA Tutor")
  126. with gr.Row():
  127. with gr.Column(scale=4):
  128. chatbot = gr.Chatbot(
  129. value=[],
  130. label="Tutoring Session",
  131. height=380
  132. )
  133. with gr.Row():
  134. msg = gr.Textbox(
  135. label="Your Question",
  136. placeholder="Ask your question here...",
  137. lines=2
  138. )
  139. submit = gr.Button("Send", variant="primary")
  140. example_questions = [
  141. "Can you help me understand quantum mechanics?",
  142. "What's the best way to learn calculus?",
  143. "Explain photosynthesis in simple terms.",
  144. "Can you create a study plan for me?",
  145. "A car accelerates uniformly from rest to a speed of 20 m/s in 5 seconds. What is the acceleration of the car?",
  146. "Balance the following chemical equation: Fe + O2 -> Fe2O3",
  147. "Find the derivative of the function f(x) = 3x^4 - 2x^3 + 5x - 7.",
  148. "Given the matrix A = [[1, 2], [3, 4]], find the determinant of A.",
  149. "Write a Python function that takes a list of integers as input and returns the sum of all even numbers in the list.",
  150. "Two forces, F1 = 20 N and F2 = 30 N, act on a point at an angle of 60° to each other. Find the magnitude and direction of the resultant force.",
  151. "In a series circuit with a 12V battery, there are two resistors: R1 = 4Ω and R2 = 6Ω. Find the current flowing through the circuit.",
  152. "Describe the basic steps in the engineering design process.",
  153. "Explain the difference between elastic and plastic deformation in materials.",
  154. "State the first law of thermodynamics and provide an example of its application in engineering."
  155. ]
  156. gr.Examples(
  157. examples=example_questions,
  158. inputs=msg,
  159. label="Example Questions"
  160. )
  161. with gr.Column(scale=1):
  162. stats = gr.Textbox(
  163. label="System Performance",
  164. lines=6,
  165. interactive=False,
  166. value=update_stats()
  167. )
  168. def respond(message, history):
  169. bot_message = generate_response(message, history)
  170. history.append([message, bot_message])
  171. new_stats = update_stats()
  172. return "", history, new_stats
  173. # Connect message input and submit button
  174. msg.submit(respond, [msg, chatbot], [msg, chatbot, stats])
  175. submit.click(respond, [msg, chatbot], [msg, chatbot, stats])
  176. # Add a refresh button for stats
  177. refresh = gr.Button("🔄 Refresh Stats")
  178. refresh.click(update_stats, outputs=[stats])
  179. if __name__ == "__main__":
  180. demo.queue()
  181. demo.launch(
  182. server_port=7860,
  183. server_name="0.0.0.0"
  184. )