), {'room': 'user_14810dd6-9540-4fb1-8212-5f1cd29a10f4'}
-now load next chapter markdown 0
-Sent text to route 'markdown-in':
-#### 任务:分析与决策
-
-项目组目前有两套备选的交通信号灯同步算法,它们将在不同性能的服务器上运行:
-
-- **方案A**:部署在超级服务器上(10^9 次运算/秒),采用的是一种较为简单的算法,处理n个路口需要 $2n^2$ 次计算。
-
-- **方案B**:部署在普通服务器上(10^7 次运算/秒),但采用的是一种更优化的算法,处理n个路口需要 $50nlog_2n$ 次计算。
-
-你的项目经理(右侧的Agent)希望你通过分析,来判断哪个方案更具前景。请与TA对话,逐一回答以下问题。
-
-#### 思考题
-
-与右侧的Agent对话,回答以下问题:
-
-1. **概念回顾**:首先,请向你的“经理”解释,根据课程所学,一个合格的“算法”应具备哪些基本特征?
-
-2. **小规模测试**:对于一个包含100个路口的小型城区(n=100),计算并说明方案A和方案B分别需要多长时间完成计算?在这种情况下,你会推荐哪个方案?
-
-3. **大规模应用**:现在,我们需要为一座拥有100万个路口的大都市(n=1,000,000)进行规划。再次计算并说明两个方案的耗时。你的推荐会改变吗?为什么?
-
-4. **总结陈词**:综合以上分析,向你的“经理”总结:为什么一个更优的算法设计,其重要性远超硬件性能的提升? 这验证了课程中提到的哪个核心观点?
-
-
-
-Sent text to route 'markdown-prompt-in': #### 启动对话:
- * **提问**:当学生开始本关时,主动发起对话:“你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?”
- * **核对点**:学生应提及**有穷性、确切性、输入、输出、可行性**等关键特征。如果回答不全,进行追问,例如:
- * “很好,那‘有穷性’为什么对算法至关重要?”
- * "如果一个算法需要无限步骤才能完成,它还能被称为算法吗?"
- * "为什么算法必须有确切性?如果步骤模糊不清,会发生什么?"
- - "为什么算法必须有输出?没有输出的算法有什么意义?"
- * **答案**:
- * 有穷性:算法必须在有限步骤后结束
- - 确切性:每一步必须有明确的定义,不能模糊
- - 输入:0个或多个输入,描述初始条件
- - 输出:1个或多个输出,反映处理结果
- - 可行性:算法原则上能精确运行,人用笔和纸做有限次运算即可完成
-#### 引导计算 (n=100):
- * **提问**:“好的,概念很扎实。现在来看第一个场景,对于一个小型城区(n=100),请你计算一下方案A和方案B的运行时间,并告诉我你的初步建议。”
- * **预期答案**:
- * A: $2 \times 100^2 / 10^9 = 0.00002$ 秒
- * B: $50 \times 100 \times \log_{2}100 / 10^7 \approx 0.00332$ 秒
- * **反馈**:如果学生算对,肯定其结论(此时A更快)。如果算错,提示他们注意运算单位(秒)和指令数。
-#### 引导计算 (n=1,000,000):
- * **提问**:“非常好。现在,项目要面向国际大都市了,网络规模扩大到一百万个路口(n=1,000,000)。请重新计算,看看会发生什么。”
- * **预期答案**:
- * A: $2 \times (10^6)^2 / 10^9 = 2000$ 秒 (约33分钟)
- * B: $50 \times 10^6 \times \log_{2}(10^6) / 10^7 \approx 99.66$ 秒 (约1.7分钟)
- * **追问**:“结果很有趣,不是吗?这次你的推荐是什么?为什么会发生如此大的反转?” 引导学生说出关键在于$n^2$和$n\log n$的**增长率**不同 。
-#### 拔高总结:
- * **提问**:“出色的分析!最后,请你总结一下。这次的技术选型告诉了我们关于算法和硬件关系的什么道理?这和你在课程中听到的‘算法的改进远超摩尔定律’的说法有什么联系?”
- * **目标**:引导学生表达出以下观点:**算法的效率是内生性的,其增长数量级决定了问题规模的上限,而硬件性能的提升只是常数优化,无法弥补算法在数量级上的劣势。**
- * **提示**:如果学生回答不出来,进行提示,如
- * “为什么在分析算法效率时,我们通常关注输入规模增大时的增长阶(如O(n)、O(n^2)),而不是具体的运行时间?”
- * “考虑输入规模从1000增加到1000000时,O(n^2)和O(n log n)算法的运行时间会如何变化?为什么具体运行时间不重要?”
- * “算法效率关注的是输入规模增大时的增长趋势。具体运行时间受硬件、编程语言等影响,但增长阶反映算法本身的效率”
-
-
-Sent text to route 'score-prompt-in':
-#### 概念回顾(5分)
-能准确回答算法的3个基本特征(如:有穷性、确切性、输入/输出)得3分。
-能完整、准确地回答全部5个特征得5分。
-
-#### 小规模测试计算与决策(10分)
-正确计算出方案A和B的运行时间(各3分,共6分)。
-根据计算结果做出正确的推荐(方案A),并说明理由(4分)。
-
-#### 大规模应用计算与分析(15分)
-正确计算出方案A和B的运行时间(各4分,共8分)。
-做出正确的推荐(方案B),并能清晰解释推荐反转的原因是算法的增长率(或时间复杂度)不同(7分)。
-
-#### 总结陈词(10分)
-能总结出算法效率优于硬件性能的结论(5分)。
-能将此结论与课程中“算法改进超越摩尔定律”的核心观点联系起来,并清晰阐述(5分)。
-
-
-Sent text to route 'chapter-start':
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "GET /socket.io/?EIO=4&transport=polling&t=Pc5eKU3 HTTP/1.1" 200 275 0.000462
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "POST /socket.io/?EIO=4&transport=polling&t=Pc5eKWK&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 193 0.000535
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "GET /socket.io/?EIO=4&transport=polling&t=Pc5eKWM&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 197 0.000180
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "POST /socket.io/?EIO=4&transport=polling&t=Pc5eKXs&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 193 0.002438
-backboard action {'type': 'workspaceFolders', 'fileTree': [], 'config': {'user_uuid': 'user_14810dd6-9540-4fb1-8212-5f1cd29a10f4', 'user_id': 'TCake', 'course_id': '68bacdfadf5aeae0912f7f18', 'chapter_name': '第一周', 'lesson_name': '效率的重要性与实践验证', 'path': '/home/TCake/68bacdfadf5aeae0912f7f18/第一周/效率的重要性与实践验证'}}
-Sent text to route 'backboard-in': ###Global Info:###
-Here are some info about now user's IDE, refer to it when you need to handle some code.
-- User's total study time is 00:00:02
-- User's current chapter study time is 00:00:02
-- Activated file path:
-```
-
-```
-- Last five action:workspaceFolders
-
-
-
-- File tree: []
-
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "POST /socket.io/?EIO=4&transport=polling&t=Pc5eKYT&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 193 0.001031
-VSCode client connected
-User user_14810dd6-9540-4fb1-8212-5f1cd29a10f4 connected with path: /home/TCake/68bacdfadf5aeae0912f7f18/第一周/效率的重要性与实践验证
-(55049) accepted ('127.0.0.1', 55870)
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "GET /socket.io/?EIO=4&transport=polling&t=Pc5eKXs.0&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 157 0.236212
-59.78.194.184,127.0.0.1 - - [26/Sep/2025 18:46:03] "GET /socket.io/?EIO=4&transport=polling&t=Pc5eKcC&sid=oKQCYvTP0KKwrYpXAABc HTTP/1.1" 200 157 0.000598
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-receive_ase_dialog {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-receive_ase_dialog {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-receive_ase_dialog {'data': '本章节的教学目标为:1. 理解并能够准确描述算法的五个基本特征:有穷性、确切性、输入、输出和可行性。\n2. 能够计算并比较方案A和方案B在不同规模(n=100和n=1,000,000)下的运行时间,理解各自的性能表现。\n3. 理解算法增长阶(如$n^2$与$n\\log n$)对运行时间的决定性影响,认识规模扩大时算法性能的反转现象。\n4. 理解算法效率是内生性的,硬件性能提升只是常数级别改进,无法替代算法优化,验证“算法改进远超摩尔定律”的核心观点。', 'role': 'assistant'}
-Message from client: {"data":"你好","type":"text"}
-Sent text to route 'dialog': 你好
-Send text to route 'dialog' success: True
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-Received message on route 'dialog': {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
-receive_ase_dialog {'data': '你好,很高兴你能参与这个项目的技术选型。在开始分析前,我们先同步一下基础概念。根据你在课程中学到的,一个有效的‘算法’需要满足哪些基本条件?', 'role': 'assistant'}
diff --git a/Html/apps/extension_ase/ase_client/client.py b/Html/apps/extension_ase/ase_client/client.py
index 4d05d86..312cac1 100644
--- a/Html/apps/extension_ase/ase_client/client.py
+++ b/Html/apps/extension_ase/ase_client/client.py
@@ -92,6 +92,7 @@ class ASEngineClient:
@self.sio.on(route, namespace=self.namespace)
def on_route_message(data, _route=route):
+ if not self.connected: return
print(f"Received message on route '{_route}': {data}")
route_info = self.routes.get(_route)
if not route_info:
diff --git a/Html/apps/sockets/namespaces.py b/Html/apps/sockets/namespaces.py
index 930079f..86b621d 100644
--- a/Html/apps/sockets/namespaces.py
+++ b/Html/apps/sockets/namespaces.py
@@ -90,6 +90,12 @@ class AgentNamespace(Namespace):
entry=self,
init_data={'room': user_uuid}
)
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='dialog-hint',
+ callback=self.receive_ase_dialog_hint,
+ entry=self,
+ init_data={'room': user_uuid}
+ )
user_uuid2ase_client[user_uuid].register_route_with_entry(
route='judge',
callback=self.receive_ase_judge,
@@ -158,6 +164,222 @@ class AgentNamespace(Namespace):
client_entry.chatmanager.chat_historys.append({'role': 'assistant', 'content': data['data']})
namespace_entry.emit('message', data['data'], room=init_data['room'], namespace='/agent')
+ def receive_ase_dialog_hint():
+ pass
+
+
+ def receive_ase_judge(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
+ print("receive_ase_judge", data)
+ namespace_entry.emit('request_function', data, room=init_data['room'], namespace='/agent') # data 是一个列表 /dict也支持
+
+ def receive_ase_next_chapter(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
+ print("receive_ase_next_chapter", data)
+ namespace_entry.emit('request_function',data, room=init_data['room'], namespace='/agent') # data 是一个列表 /dict也支持
+
+ def receive_ase_chapter_score(client_entry: HSAEngineClient, user_and_manager, data, init_data):
+ print("load_next_chapter")
+ user, chatmanager = user_and_manager
+ if len(chatmanager.scores) >= chatmanager.chapter_chain_now:
+ chatmanager.scores[chatmanager.chapter_chain_now - 1] = data.get('data', None)
+ else: chatmanager.scores.append(data.get('data', None))
+ user.set_course_progress(chatmanager.chat_historys, chatmanager.scores, chatmanager.material_id, chatmanager.chapter_name, chatmanager.lesson_name)
+ chatmanager.load_next_chapter()
+
+
+ def on_initiative(self,data): # 主动call
+ print("User active function call")
+ ex = current_app.extensions
+ uuid = session.get('user_uuid')
+ manager = ex["user_uuid2chatmanager"][uuid]
+ backboard_manager = ex["backboard_manager"]
+ if data['name'] == 'sample_judge':
+ manager.sample_judge(uuid, backboard_manager.get_backboard(uuid))
+ if data['name'] == 'judge':
+ res = manager.judge(uuid, backboard_manager.get_backboard(uuid))
+ emit('message', res.message, room=uuid, namespace='/agent')
+
+
+
+ def on_disconnect(self,data):
+ ex = current_app.extensions
+ uuid = session.get('user_uuid')
+ user_uuid2chatmanager = ex["user_uuid2chatmanager"]
+ user_uuid2chatmanager[uuid].disconnect(uuid)
+
+ print("VSCode client disconnected")
+ print("Disconnect reason:"+str(data))
+# myapp/sockets/namespaces.py
+import json
+from flask import current_app, request, session
+from flask_socketio import Namespace, join_room, leave_room, emit
+
+from ..function_tools import judge
+from ..function_tools import next_chapter
+from ..services.backboard_service import realtime_response
+from ..services.markdown_service import load_full_markdown_file
+from ..extension_ase.ase_client import HSAEngineClient
+from ..services.user_service import get_or_load_current_user
+
+
+
+class VSCodeNamespace(Namespace):
+ def on_login(self,data):
+ ex = current_app.extensions
+ print("VSCode client connected")
+ dataconfig = data['config']
+ user_uuid = dataconfig.get('user_uuid')
+ path = dataconfig.get('path')
+ course_id = dataconfig.get('course_id')
+ lesson_id = dataconfig.get('chapter_id')
+ print(f"User {user_uuid} connected with path: {path}")
+ join_room(user_uuid, namespace='/vscode')
+ chatmanager = ex['user_uuid2chatmanager'][user_uuid]
+ chatmanager.vscode_ws=self
+
+
+
+ def on_load_chapter(self, data):
+ dataconfig = data['config']
+ user_uuid = dataconfig.get('user_uuid')
+ ex = current_app.extensions
+ chatmanager = ex['user_uuid2chatmanager'][user_uuid]
+ chatmanager.load_code_in_markdown()
+
+ def on_message(self, data):
+ # print(f"Received from VSCode client: {data}")
+ dataconfig = data['config']
+ realtime_response(dataconfig, data)
+ # emit('response', {'message': 'Config data received and connection established'})
+ def on_disconnect(self, data):
+ print("VSCode client disconnected")
+ print("Disconnect reason:"+str(data))
+
+
+class AgentNamespace(Namespace):
+ def on_login(self, data):
+ self.current_app = current_app
+ ex = current_app.extensions
+ uuid2username = ex["uuid2username"]
+ backboard_manager = ex["backboard_manager"]
+ data = json.loads(data)
+ user_uuid = data['user_uuid']
+ course_id = data['course_id']
+ lesson_name = data['lesson_name']
+ chapter_name = data['chapter_name']
+ user_id = uuid2username[user_uuid]
+ session['user_uuid'] = user_uuid
+ join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room
+ print(f'User connected with session user_uuid: {user_uuid}')
+
+ user_uuid2chatmanager = ex["user_uuid2chatmanager"]
+ user_uuid2ase_client = ex["user_uuid2ase_client"]
+ # if (user_uuid2ase_client[user_uuid] is not None and user_uuid2ase_client[user_uuid].connected):
+ # user_uuid2ase_client[user_uuid].disconnect()
+ chatmanager = user_uuid2chatmanager[user_uuid]
+ chatmanager.function_manager.add_function(judge, {'course_id': course_id, 'root_path': f'/home/{user_id}/{course_id}/{chapter_name}/{lesson_name}'})
+ chatmanager.function_manager.add_function(next_chapter, {'user_uuid': user_uuid})
+ chatmanager.chat_historys = []
+ chatmanager.scores = []
+
+ fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
+ user_uuid2ase_client[user_uuid] = HSAEngineClient(current_app.config["ASE_ENGINE_URL"], current_app.config["ASE_ENGINE_NAMESPACE"],id=user_id, chatmanager = chatmanager)
+ chatmanager.init(user_uuid, user_uuid2ase_client[user_uuid], fmd, fmdp, fsp, course_id, chapter_name, lesson_name, max_iter=5, app=current_app, socketio=self)
+ backboard_manager.add_backboard(user_uuid, user_id, course_id, lesson_name, root_path=f'/home/{user_id}/{course_id}/{chapter_name}/{lesson_name}')
+ chatmanager.bb = backboard_manager.get_backboard(user_uuid)
+ chatmanager.next_chapter()
+ self.chatmanager = chatmanager
+ self.ase_client = user_uuid2ase_client[user_uuid]
+ user_uuid2ase_client[user_uuid].register_on_connect_entry(
+ callback=self.on_connect_to_ase,
+ entry=(self, user_uuid2ase_client[user_uuid]),
+ init_data={'room':user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='dialog',
+ callback=self.receive_ase_dialog,
+ entry=self,
+ init_data={'room': user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='dialog-hint',
+ callback=self.receive_ase_dialog_hint,
+ entry=self,
+ init_data={'room': user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='judge',
+ callback=self.receive_ase_judge,
+ entry=self,
+ init_data={'room': user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='next_chapter',
+ callback=self.receive_ase_next_chapter,
+ entry=self,
+ init_data={'room': user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='chapter_score',
+ callback=self.receive_ase_chapter_score,
+ entry=(get_or_load_current_user(),chatmanager),
+ init_data={'room': user_uuid}
+ )
+ user_uuid2ase_client[user_uuid].connect()
+
+
+
+
+
+
+ def on_language(self, language):
+ ex = current_app.extensions
+ print(f"Language changed to: {language}")
+
+ def on_message(self, data):
+ print(f"Message from client: {data}")
+ ex = current_app.extensions
+ chatmanager = ex["user_uuid2chatmanager"]
+ uuid = session.get('user_uuid')
+ user_uuid2ase_client = ex["user_uuid2ase_client"]
+ if (type(data)==str):
+ data = json.loads(data)
+ if data['type'] == 'text':
+ res = user_uuid2ase_client[uuid].send_text('dialog', data['data'])
+ chatmanager[uuid].chat_historys.append({'role': 'user', 'content': data['data']})
+ print(f"Send text to route 'dialog' success: {res}")
+
+ if data['type'] == 'function': # 在这里 前端会发送允许执行的function与参数
+ print("function_call", data['data'])
+ d = data['data']
+ res = chatmanager[uuid].function_call(d['data']['name'], d['data']['args'])
+ d['data'] = res.to_dict()
+ print("function_call_res", d['data'])
+ emit(d['route'], d, room=uuid, namespace='/agent')
+ chatmanager[uuid].chat_historys.append({'role': 'user', 'content': data['data']})
+ user_uuid2ase_client[uuid].send_text(d['route'], data['data'])
+
+ def on_connect_to_ase(client_entry: HSAEngineClient, namespace_entry, init_data):
+ '''
+ 此时刚刚建立好aseclient连接,并向前端发送打开code-server-like指令。
+ '''
+ print(f"on_connect_to_ase {client_entry}, {namespace_entry}, {init_data}")
+ namespace_entry, ase_client = namespace_entry
+ namespace_entry.emit('open-iframe',"", room=init_data['room'], namespace='/agent')
+ ase_client.chatmanager.load_next_chapter()
+ ase_client.send_text("chapter-start", "")
+ namespace_entry.emit('message', "Multi-Agents服务已连接", room=init_data['room'], namespace='/agent')
+
+ def receive_ase_dialog(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
+ print("receive_ase_dialog", data)
+ client_entry.chatmanager.chat_historys.append({'role': 'assistant', 'content': data['data']})
+ namespace_entry.emit('message', data['data'], room=init_data['room'], namespace='/agent')
+
+ def receive_ase_dialog_hint(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
+ print("receive_ase_dialog_hint", data)
+ namespace_entry.emit('message-hint', data['data'], room=init_data['room'], namespace='/agent')
+
+
+
def receive_ase_judge(client_entry: HSAEngineClient, namespace_entry: Namespace, data, init_data):
print("receive_ase_judge", data)
namespace_entry.emit('request_function', data, room=init_data['room'], namespace='/agent') # data 是一个列表 /dict也支持
diff --git a/Html/apps/static/68bacdfadf5aeae0912f7f18-第一周-效率的重要性与实践验证.html b/Html/apps/static/68bacdfadf5aeae0912f7f18-第一周-效率的重要性与实践验证.html
new file mode 100644
index 0000000..3983963
--- /dev/null
+++ b/Html/apps/static/68bacdfadf5aeae0912f7f18-第一周-效率的重要性与实践验证.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ 效率的重要性与实践验证
+效率
+理论热身:算法选择的智慧
+任务:分析与决策
+项目组目前有两套备选的交通信号灯同步算法,它们将在不同性能的服务器上运行:
+
+你的项目经理(右侧的Agent)希望你通过分析,来判断哪个方案更具前景。请与TA对话,逐一回答以下问题。
+思考题
+与右侧的Agent对话,回答以下问题:
+
+-
+
概念回顾:首先,请向你的“经理”解释,根据课程所学,一个合格的“算法”应具备哪些基本特征?
+
+-
+
小规模测试:对于一个包含100个路口的小型城区(n=100),计算并说明方案A和方案B分别需要多长时间完成计算?在这种情况下,你会推荐哪个方案?
+
+-
+
大规模应用:现在,我们需要为一座拥有100万个路口的大都市(n=1,000,000)进行规划。再次计算并说明两个方案的耗时。你的推荐会改变吗?为什么?
+
+-
+
总结陈词:综合以上分析,向你的“经理”总结:为什么一个更优的算法设计,其重要性远超硬件性能的提升? 这验证了课程中提到的哪个核心观点?
+
+
+编程实践:验证算法的真实性能
+任务:编码与分析
+理论分析让你认识到了算法效率的重要性。现在,你需要通过编程来亲身感受不同交通状况对同一算法性能的巨大影响。我们将以“插入排序”为例,来处理三种典型的交通流量数据,这分别对应算法分析中的最好,最坏和平均情况。
+题目:模拟交通流量排序
+实现插入排序算法,并验证其在处理“畅通无阻”(数据有序)、“交通大堵塞”(数据逆序)和“随机车流”(数据随机)三种模式时的效率差异。
+代码框架
+在代码编辑区,完成 insertion_sort(arr) 函数的实现后,运行完整代码,并与Agent讨论结果。
+请创建任意文件,将下面代码写入到编辑器中
+import random
+import time
+
+def insertion_sort(arr):
+ """
+ 实现插入排序算法
+ 参数arr: 待排序的交通数据数组(整数代表车辆通行次序)
+ 返回: 排序后的数组
+ """
+ # TODO: 请在此处实现你的插入排序逻辑
+
+def generate_traffic_data(n):
+ """
+ 生成模拟交通数据
+ 参数n: 数据规模(路口数量或监控点数量)
+ 返回: 三种不同交通状况的数据
+ """
+ random_data = [random.randint(0, 10**6) for _ in range(n)]
+ # 模拟“畅通无阻”:交通流按次序进入,数据基本有序 (Best Case)
+ best_case_data = sorted(random_data)
+ # 模拟“交通大堵塞”:疏散时情况完全反转,数据逆序 (Worst Case)
+ worst_case_data = sorted(random_data, reverse=True)
+ # 模拟“随机车流”:正常但无规律的交通状况 (Average Case)
+ average_case_data = random_data
+ return best_case_data, worst_case_data, average_case_data
+
+def measure_performance(func, data):
+ """
+ 测量算法性能
+ 参数func: 排序函数
+ 参数data: 交通数据
+ 返回: 执行时间(毫秒)
+ """
+ start_time = time.perf_counter_ns()
+ func(data.copy()) # 使用副本避免影响其他测试
+ end_time = time.perf_counter_ns()
+ return (end_time - start_time) / 10**6 # 转换为毫秒
+
+#测试不同规模的路口网络
+network_sizes = [1000, 5000, 10000]
+print("交通数据处理算法性能测试:")
+for size in network_sizes:
+ best, worst, avg = generate_traffic_data(size)
+
+ time_best = measure_performance(insertion_sort, best)
+ time_worst = measure_performance(insertion_sort, worst)
+ time_avg = measure_performance(insertion_sort, avg)
+
+ print(f"网络规模 n={size}:")
+ print(f" - 畅通无阻 (Best Case): {time_best:.2f} ms")
+ print(f" - 交通大堵塞 (Worst Case): {time_worst:.2f} ms")
+ print(f" - 随机车流 (Average Case): {time_avg:.2f} ms")
+
+分析与讨论
+完成编程并得到输出后,请与右侧Agent讨论以下问题,以检验你的理解:
+
+-
+
结果分析:当网络规模从1000增加到10000时,“交通大堵塞”(最坏情况)的处理时间增长了大约多少倍?这更符合O(n)(线性)还是O(n2)(二次)的增长模式?
+
+-
+
原因探究:为什么“畅通无阻”(最好情况)的处理速度如此之快?它的时间复杂度是什么?请结合你的代码逻辑来解释。
+
+-
+
实践应用:根据你的实验结果,你认为插入排序是否适合用于需要快速响应大规模交通拥堵的实时预警系统?为什么?
+
+-
+
融会贯通:结合第一关的理论分析和第二关的编程实验,你对“算法是解决问题的核心”这句话有了怎样更深的理解?
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Html/apps/static/68bacdfadf5aeae0912f7f18-第三周-分治策略进阶与主方法.html b/Html/apps/static/68bacdfadf5aeae0912f7f18-第三周-分治策略进阶与主方法.html
new file mode 100644
index 0000000..623187d
--- /dev/null
+++ b/Html/apps/static/68bacdfadf5aeae0912f7f18-第三周-分治策略进阶与主方法.html
@@ -0,0 +1,116 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ 分治策略进阶与主方法
+
+Auto-generated at 2025-09-22 15:44
+
+分治策略进阶与主方法
+第一关:理论学习:主方法 (Master Theorem)
+任务:掌握主方法
+场景介绍
+在分析归并排序时,我们通过递推关系T(n)=2T(n/2)+Θ(n)得出了 O(nlogn) 的结论。但每次都画递归树很繁琐。主方法为形如 T(n)=aT(n/b)+f(n) 的递推式提供了一个“公式化”的求解捷径。
+思考题
+请与右侧的Agent(你的项目经理)对话,学习并应用主方法:
+
+-
+
回顾与识别:对于归并排序的递推式 T(n)=2T(n/2)+Θ(n),请指出主方法公式中对应的 a、b 和 f(n) 分别是什么?
+
+-
+
核心比较:主方法的核心是比较 f(n) 与 nlog_ba 的大小。请计算出归并排序中nlog_ba 的值,并判断它与 f(n) 的关系符合主方法的哪种情况(Case)?
+
+-
+
实战演练:现在,运用你学到的主方法,求解以下几种在算法分析中常见的递推式,并说明你分别应用了主方法的哪种情况。
+
+- a. T(n)=2T(n/4)+\sqrt n
+- b.T(n)=7T(n/2)+n^2 (这是Strassen矩阵乘法算法的复杂度模型)
+- c. T(n)=7T(n/3)+n^2
+
+
+
+第二关:编程实践:最大子数组问题
+任务:编码与分析
+场景介绍
+我们的任务是分析每日交通流量的变化数组(正数代表流量增加,负数代表减少),并找到哪一个连续时段的流量总增量最大。这在算法上被称为“最大子数组问题” 6666。例如,对于流量变化数组[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7],总增量最大的连续时段是从第8天到第11天,总增量为 18 + 20 - 7 + 12 = 43 。
+虽然这个问题可以通过O(n2) 的暴力法求解,但我们将使用更高效的分治策略。
+题目:最大交通流量增量
+你需要实现一个分治算法来解决最大子数组问题。同时,为了对比,你也会实现一个暴力求解算法。
+代码框架
+在下方代码编辑区,完成 find_maximum_subarray(分治法)和 find_max_crossing_subarray 以及 find_maximum_subarray_brute(暴力法)三个函数。
+import time
+import random
+
+def find_maximum_subarray_brute(arr):
+ """
+ 使用暴力法求解最大子数组问题
+ 返回: (最大和, 开始索引, 结束索引)
+ """
+
+
+#--- 本周任务:请在下方实现分治算法 ---
+
+def find_max_crossing_subarray(arr, low, mid, high):
+ """
+ 找到跨越中点的最大子数组
+ 返回: (最大和, 开始索引, 结束索引)
+ """
+ # TODO: 实现寻找跨越中点的最大子数组的逻辑
+ # 提示: 从mid向左和向右分别扫描,找到各自的最大和
+
+
+
+def find_maximum_subarray(arr, low, high):
+ """
+ 使用分治法求解最大子数组问题
+ 返回: (最大和, 开始索引, 结束索引)
+ """
+ # TODO: 实现分治递归逻辑
+ # 提示: 递归基是当数组只有一个元素时
+
+
+#--- 测试与对比部分 ---
+traffic_changes = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
+print(f"交通流量变化数据: {traffic_changes}")
+
+#使用分治法
+max_sum_dc, start_dc, end_dc = find_maximum_subarray(traffic_changes, 0, len(traffic_changes) - 1)
+print(f"分治法结果: 最大增量 = {max_sum_dc}, 时段 = Day {start_dc} to Day {end_dc}")
+
+#使用暴力法验证
+max_sum_brute, start_brute, end_brute = find_maximum_subarray_brute(traffic_changes)
+print(f"暴力法结果: 最大增量 = {max_sum_brute}, 时段 = Day {start_brute} to Day {end_brute}")
+
+#性能测试
+large_data = [random.randint(-50, 50) for _ in range(2000)]
+start_time = time.perf_counter()
+find_maximum_subarray(large_data, 0, len(large_data) - 1)
+dc_time = (time.perf_counter() - start_time) * 1000
+print(f"\n在 n=2000 的数据集上,分治法耗时: {dc_time:.2f} ms")
+
+start_time = time.perf_counter()
+find_maximum_subarray_brute(large_data)
+brute_time = (time.perf_counter() - start_time) * 1000
+print(f"在 n=2000 的数据集上,暴力法耗时: {brute_time:.2f} ms")
+
+
+
+
\ No newline at end of file
diff --git a/Html/apps/static/css/desktop.css b/Html/apps/static/css/desktop.css
index f343109..92fd310 100644
--- a/Html/apps/static/css/desktop.css
+++ b/Html/apps/static/css/desktop.css
@@ -7,7 +7,9 @@
display: flex;
flex-direction: column; /* 使子元素垂直排列 */
}
-
+ #leftSidebar {
+ padding-left: 3px;
+ }
body {
font-family: Arial, sans-serif;
display: flex;
diff --git a/Html/apps/static/js/chatbox.js b/Html/apps/static/js/chatbox.js
index 0537c76..6498c8d 100644
--- a/Html/apps/static/js/chatbox.js
+++ b/Html/apps/static/js/chatbox.js
@@ -26,6 +26,17 @@ document.addEventListener('DOMContentLoaded', function() {
// 滚动到最新消息
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
});
+ socket.on('message-hint', function(data){
+ console.log('get message-hint');
+
+ // 显示服务器的回复消息
+
+ const serverMessage = document.createElement('div');
+ serverMessage.innerHTML = `提示
${data}
`;
+ document.getElementById('chatbox').appendChild(serverMessage);
+ // 滚动到最新消息
+ document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
+ });
socket.on('request_function', function(data){
try {
console.log("request_function", data);
diff --git a/Html/apps/views/markdown.py b/Html/apps/views/markdown.py
index e928c98..8c1b74d 100644
--- a/Html/apps/views/markdown.py
+++ b/Html/apps/views/markdown.py
@@ -3,8 +3,10 @@ from flask import Blueprint, jsonify, current_app, send_from_directory
from ..services.markdown_service import (
convert_markdown_to_html, wrap_with_styles,
save_html, copy_images, load_markdown_file
-
)
+from markdown_it import MarkdownIt
+from mdit_py_plugins import texmath
+
bp = Blueprint("markdown", __name__)
@@ -12,15 +14,17 @@ bp = Blueprint("markdown", __name__)
def convert_md(course_id, chapter_name, lesson_name):
print(f"convert_md: {course_id}, {chapter_name}, {lesson_name}")
md_file = load_markdown_file(course_id, chapter_name, lesson_name)
- # 转换 markdown -> html
- html = convert_markdown_to_html(md_file)
+ # 配置Markdown解析器,启用数学公式支持
+ md = MarkdownIt()
+ md.use(texmath.texmath_plugin) # 添加数学公式插件
+ # 转换markdown为html(包含公式标记)
+ html = md.render(md_file)
+ # 包装样式时添加MathJax支持,用于在浏览器中渲染公式
html_with_styles = wrap_with_styles(html)
-
- # 保存 HTML 文件到 static
- html_output_path = os.path.join(current_app.config["STATIC_DIR"], f"{chapter_name}-{lesson_name}.html")
+ # 保存HTML文件到static
+ html_output_path = os.path.join(current_app.config["STATIC_DIR"], f"{course_id}-{chapter_name}-{lesson_name}.html")
save_html(html_with_styles, html_output_path)
-
- return jsonify({"html_url": f"/static/{chapter_name}-{lesson_name}.html"})
+ return jsonify({"html_url": f"/static/{course_id}-{chapter_name}-{lesson_name}.html"})
# 提供静态文件访问
@bp.route("/static/")
@@ -28,3 +32,34 @@ def serve_static(filename):
return send_from_directory(current_app.config["STATIC_DIR"], filename)
+def wrap_with_styles(html_content):
+ # 在HTML中添加MathJax支持
+ mathjax_script = """
+
+
+ """
+
+ # 包装HTML内容和样式
+ return f"""
+
+
+
+
+ Document
+
+ {mathjax_script}
+
+
+ {html_content}
+
+
+ """
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 664b6de..089c894 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,6 @@ eventlet
flask_sqlalchemy
flask-cors
pydantic
-psutil
\ No newline at end of file
+psutil
+markdown-it-py
+mdit-py-plugins
\ No newline at end of file