This commit is contained in:
CakeCN
2025-01-01 01:43:28 +08:00
parent 1280a978f5
commit eb67bcfb70
115 changed files with 989 additions and 535 deletions

View File

@@ -9,10 +9,24 @@ import sys
import json
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, parent_dir)
student_workspace_root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../study'))
current_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '.'))
sys.path.insert(0, current_dir)
from AlgoriAgent.projects.algoriAgent.agent_manager import AgentManager
import configparser
from db.user_list import UserList
from db.user import User, load_user_from_json, create_user_json
from db.course_list import CourseList
from db.course import Course, load_course_from_json
GLOBAL_CONFIG = configparser.ConfigParser()
GLOBAL_CONFIG.read('config.ini')
VSCODE_WEB_URL = GLOBAL_CONFIG['VSCODE_WEB']['url']
USER_DATA_DIR = GLOBAL_CONFIG['USER_DATA']['dir']
COURSE_DATA_DIR = GLOBAL_CONFIG['COURSE_DATA']['dir']
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*",ping_timeout=60, ping_interval=5)
# socketio = SocketIO(app, cors_allowed_origins="http://localhost:9888") # 设置跨域支持
@@ -20,7 +34,7 @@ import logging
app.secret_key = 'cakebaker'
app.logger.setLevel(logging.DEBUG)
# 配置 CORS
CORS(app, resources={r"/*": {"origins": "http://127.0.0.1:9090"},}, supports_credentials=True)
CORS(app, resources={r"/*": {"origins": VSCODE_WEB_URL},}, supports_credentials=True)
userid_recorder = {} # user_id&path -> session['user_id']
@@ -31,8 +45,8 @@ Backboard
from backboardManager import BackBoardManager, Backboard
backboard_manager = BackBoardManager()
uuid2user_id = {}
user_id2uuid = {}
uuid2username = {}
username2uuid = {}
@@ -45,7 +59,7 @@ class VSCodeNamespace(Namespace):
user_id = dataconfig.get('user_id')
path = dataconfig.get('path')
print(f"User {user_id} connected with path: {path}")
useruuid = user_id2uuid[user_id]
useruuid = username2uuid[user_id]
join_room(useruuid, namespace='/vscode')
if backboard_manager.get_backboard(useruuid) == None:
backboard_manager.add_backboard(useruuid, path)
@@ -56,14 +70,15 @@ class VSCodeNamespace(Namespace):
dataconfig = data['config']
realtime_response(dataconfig, data)
# emit('response', {'message': 'Config data received and connection established'})
def on_disconnect(self):
def on_disconnect(self, data):
print("VSCode client disconnected")
print("Disconnect reason:"+str(data))
def realtime_response(config, realtime_action):
user_id = config['user_id']
folder_path = config['path']
useruuid = user_id2uuid[user_id]
useruuid = username2uuid[user_id]
bb = backboard_manager.get_backboard(useruuid)
assert type(bb) == Backboard
@@ -75,14 +90,12 @@ def realtime_response(config, realtime_action):
if realtime_action['type'] == 'activeFile':
file_path = realtime_action['filePath']
assert type(file_path) == str
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
bb.active_file_path = file_path
with open(f"../{user_id}/{folder_path}/{file_path}") as f:
with open(f"{file_path}") as f:
bb.active_file_content = f.read()
if realtime_action['type'] == 'paste':
file_path = realtime_action['filePath']
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
file_path = realtime_action['filePath']
assert type(file_path) == str
bb.pasted_file_path = file_path
bb.pasted_content = realtime_action['content']
@@ -106,21 +119,22 @@ class AgentNamespace(Namespace):
def on_login(self, data):
data = json.loads(data)
user = data['username']
folder_name = data['folder']
user_uuid = user_id2uuid[user]
course_id = data['course_id']
chapter_id = data['chapter_id']
user_uuid = username2uuid[user]
session['user_id'] = user_uuid
print(f'User connected with session user_id: {user_uuid}')
# 从markdown、markdown_prompts、score_prompts中各读取数据folder.md并进行new_agent
with open(f'books/markdown/{folder_name}.md','r',encoding='UTF-8') as fmd,\
open(f'books/markdown_prompts/{folder_name}.md','r',encoding='UTF-8')as fmdp,\
open(f'books/score_prompts/{folder_name}.md','r',encoding='UTF-8') as fsp:
with open(f'books/markdown/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fmd,\
open(f'books/markdown_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8')as fmdp,\
open(f'books/score_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fsp:
markdown = fmd.read()
markdown_prompts = fmdp.read()
score_prompts = fsp.read()
user_uuid, agent = agent_manager.new_agent(markdown, markdown_prompts, score_prompts, id=user_uuid, root_path=f'{user}/{folder_name}')
user_uuid, agent = agent_manager.new_agent(course_id, chapter_id, markdown, markdown_prompts, score_prompts, id=user_uuid, root_path=f'{user}/{course_id}/{chapter_id}')
print(user_uuid)
join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room
backboard_manager.add_backboard(user_uuid, folder_name)
backboard_manager.add_backboard(user_uuid, chapter_id)
def on_language(self, language):
id = session.get('user_id')
@@ -154,8 +168,9 @@ class AgentNamespace(Namespace):
agent_manager.function_call(id, data['data'])
def on_disconnect(self):
def on_disconnect(self,data):
print("VSCode client disconnected")
print("Disconnect reason:"+str(data))
@@ -169,9 +184,9 @@ IMAGE_DIR = 'image' # 图片资源相对于 markdown 的位置
@app.route('/<filename>-markdown', methods=['GET'])
def convert_md(filename):
md_file_path = os.path.join(MARKDOWN_DIR, f'{filename}.md')
@app.route('/<course_id>-<filename>-markdown', methods=['GET'])
def convert_md(course_id, filename):
md_file_path = os.path.join(MARKDOWN_DIR,course_id, f'{filename}.md')
if not os.path.exists(md_file_path):
return jsonify({'error': 'Markdown file not found'}), 404
@@ -205,7 +220,7 @@ def convert_md(filename):
html_file.write(html_with_styles)
# 处理图片资源,将 image/xxx 文件夹拷贝到 static/image/xxx
image_source_dir = os.path.join(MARKDOWN_DIR, IMAGE_DIR, filename)
image_source_dir = os.path.join(MARKDOWN_DIR,course_id, IMAGE_DIR, filename)
image_target_dir = os.path.join(STATIC_DIR, IMAGE_DIR, filename)
print(f"Copying image resources from {image_source_dir} to {image_target_dir}")
if os.path.exists(image_source_dir):
@@ -230,25 +245,35 @@ def serve_static(filename):
'''
Vscode
'''
@app.route('/desktop/<user_id>/<path>')
def hello_world(user_id, path):
@app.route('/desktop/<user_id>/<course_id>/<chapter_id>')
def desktop(user_id, course_id, chapter_id):
if 'user_id' not in session:
# return redirect(url_for('login'))
session['user_id'] = 'user_' + str(uuid.uuid4())
print("user "+ user_id + "uuid is"+ session['user_id'])
user_id2uuid[user_id] = session['user_id']
uuid2user_id[session['user_id']] = user_id
userid_recorder[user_id+'&'+path] = session['user_id']
username2uuid[user_id] = session['user_id']
uuid2username[session['user_id']] = user_id
userid_recorder[user_id+'&'+course_id] = session['user_id']
# 在上层 目录下创建一个名为 user_id_path 的文件夹
path_dir = os.path.join(parent_dir, user_id, path)
# 在学习目录下创建一个名为 user_id_path 的文件夹
path_dir = os.path.join(student_workspace_root_path, user_id, course_id,chapter_id)
os.makedirs(path_dir, exist_ok=True)
# 在此文件夹内部创建一个.config文件并写入 user_id=user_id\n path=path
config_path = os.path.join(path_dir, '.config')
print('---------------------')
print(config_path)
with open(config_path, 'w') as f:
f.write(f"user_id={user_id}\npath={path}")
return render_template('desktop.html', user_id=user_id, path=path)
tmpd = {'user_id': user_id, 'course_id': course_id, 'chapter_id': chapter_id, 'path': path_dir}
json.dump(tmpd, f)
return render_template('desktop.html', vscode_web_url=VSCODE_WEB_URL, user_id=user_id, course_id=course_id, chapter_id=chapter_id, workspace_path=path_dir)
@app.route('/desktop_nouser/<course_id>/<chapter_id>')
def desktop_nouser(course_id, chapter_id):
if 'user_id' not in session:
return redirect(url_for('login'))
user_id = session['user_id']
username = uuid2username[user_id]
return redirect(url_for('desktop', user_id=username, course_id=course_id, chapter_id=chapter_id))
@app.route('/vscode_data', methods=['POST'])
def vscode_data():
@@ -269,17 +294,33 @@ def get_session():
Login
'''
users_list = UserList()
course_list = CourseList()
@app.route('/register')
def register():
return render_template('register.html')
@app.route('/register_post', methods=['POST'])
def register_post():
data = request.get_json()
username = data.get('username')
password = data.get('password')
if users_list.has_user(username) is not None:
users_list.add_user(username, password)
create_user_json(username, USER_DATA_DIR)
return jsonify({'success': True, 'message': '注册成功'})
else: return jsonify({'success': False, 'message': '用户已存在,请更换用户名'})
@app.route('/login')
def login():
return render_template('login.html')
if 'user_id' not in session:
return render_template('login.html')
else:
return redirect(url_for('/'))
from db.user_list import UserList
users_list = UserList()
@app.route('/login_post', methods=['POST'])
def login_post():
# 获取请求的 JSON 数据
@@ -288,44 +329,81 @@ def login_post():
username = data.get('username')
password = data.get('password')
user = users_list.get_user(username)
if user is None:
return jsonify({'success': False, 'message': '用户名或密码错误'})
pswd = users_list.get_user_pswd(username)
if user['password'] != password:
if pswd is None:
return jsonify({'success': False, 'message': '用户名或密码错误'})
if pswd != password:
return jsonify({'success': False, 'message': '用户名或密码错误'})
session['user_id'] = 'user_' + str(uuid.uuid4())
print("user "+ username + "uuid is"+ session['user_id'])
user_id2uuid[username] = session['user_id']
uuid2user_id[session['user_id']] = username
username2uuid[username] = session['user_id']
uuid2username[session['user_id']] = username
return jsonify({'success': True, 'message': '登录成功'})
user_id2UserClass = {}
'''
DashBoard
'''
@app.route('/dashboard')
def dashboard():
if 'user_id' not in session:
if 'user_id' not in session or session['user_id'] not in uuid2username:
return redirect(url_for('login'))
return render_template('dashboard.html')
user_id = session['user_id']
username = uuid2username[user_id]
if (user_id not in user_id2UserClass):
user_id2UserClass[user_id] = load_user_from_json(username, user_data_dir = USER_DATA_DIR)
user_course_data = []
for course_id in user_id2UserClass[user_id].select_course:
course_brief_info = course_list.get_course_brief_info(course_id, load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR))
user_course_data.append(course_brief_info)
return render_template('dashboard.html',user_data = json.dumps(user_id2UserClass[user_id].__json__()), user_course_data = json.dumps(user_course_data))
'''
Book
Course
'''
@app.route('/book/<book_name>')
def book(book_name):
return render_template('book.html', book_name=book_name)
@app.route('/course/<course_id>')
def course(course_id):
c = load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR)
return render_template('course.html', course_id=course_id, course_data=c)
@app.route('/select_course', methods=['POST'])
def select_course():
if ('user_id' not in session or session['user_id'] not in user_id2UserClass):return redirect(url_for('login'))
user = user_id2UserClass[session['user_id']]
data = request.get_json()
course_id = data.get('course_id')
if course_id:
user.select_new_course(course_id, load_course_from_json(course_id, COURSE_DATA_DIR))
return jsonify({'success': True, 'message': '课程选择成功'})
@app.route('/')
def home_index():
return render_template('index.html')
selected_courses=[]
if ('user_id' in session):
if (session['user_id'] not in user_id2UserClass): return redirect(url_for('login'))
user = user_id2UserClass[session['user_id']]
for course_id in user.select_course:
selected_courses.append(course_id)
return render_template('index.html', courses_data = course_list, selected_courses =selected_courses)
# 一些app辅助函数主要提供给Agent与数据库的交互能力
class MyFunction:
def save_chapter_memory(self, id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal):
print("-=-=-=-=-=-=-=-")
print(id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
username = uuid2username[id]
u = load_user_from_json(username, user_data_dir = USER_DATA_DIR)
u.save_chapter_memory(course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
app.my_function = MyFunction()
if __name__ == '__main__':
socketio.on_namespace(VSCodeNamespace('/vscode'))
socketio.on_namespace(AgentNamespace('/agent'))
socketio.run(app, host='0.0.0.0', port=5000, debug=True)