fix many bug

This commit is contained in:
Cai
2025-09-24 11:29:31 +08:00
parent 6aac420062
commit 07cf2363ab
21 changed files with 551 additions and 1684 deletions

View File

@@ -25,6 +25,12 @@ class ASEngineClient:
# 存储路由和对应的回调函数
self.routes: Dict[str, Dict[str, Callable]] = {}
self._on_connect_callback = None
self._on_connect_callback_entry=None
self._on_connect_callback_initData=None
# 注册基础事件处理函数
self._register_base_events()
@@ -36,7 +42,9 @@ class ASEngineClient:
self.connected = True
self.sid = self.sio.get_sid(namespace=self.namespace)
print(f"Connected to server. SID: {self.sid}")
if self._on_connect_callback is not None:
self._on_connect_callback(self._on_connect_callback_entry, self._on_connect_callback_initData)
# 断开连接事件
@self.sio.on('disconnect', namespace=self.namespace)
def on_disconnect():
@@ -55,6 +63,14 @@ class ASEngineClient:
def on_response(data):
print(f"Received response: {data}")
def register_on_connect_entry(self, callback: Callable, entry: Any, init_data: Any)->bool:
if not callable(callback):
return False
self._on_connect_callback = callback
self._on_connect_callback_entry=entry
self._on_connect_callback_initData=init_data
def register_route_with_entry(self, route: str,
callback: Optional[Callable] = None,
entry: Any = None,
@@ -138,7 +154,8 @@ class ASEngineClient:
# 等待连接建立
start_time = time.time()
while not self.connected and (time.time() - start_time) < timeout:
time.sleep(0.1)
print(f"Connecting To {self.server_url}")
time.sleep(0.2)
return self.connected
except Exception as e:
print(f"Connection failed: {e}")
@@ -264,8 +281,9 @@ class ASEngineClient:
class HSAEngineClient(ASEngineClient):
def __init__(self, server_url: str, namespace: str, id:str):
def __init__(self, server_url: str, namespace: str, id:str, chatmanager):
super().__init__(server_url, namespace, id)
self.chatmanager = chatmanager
def loadmarkdown(self, fmd, fmdp, fsp):
self.send_text('markdown-in', fmd, self.id)
self.send_text('markdown-prompt-in', fmdp, self.id)

View File

@@ -29,11 +29,25 @@ class ChatManager:
_procs: Dict[str, ProcRecord] = {}
_lock = threading.RLock()
def __init__(self):
self.chapter_chain_now = -1
self.ase_client = None
self.app = None
self.socketio = None
self.user_uuid = None
self.raw_markdown = None
self.raw_markdown_prompts = None
self.raw_score_prompts = None
self.material_id = None
self.chapter_name = None
self.lesson_name = None
self.chapter_chain = None
self.function_manager = FunctionManager()
self.bb = None
self.chat_historys = None
pass
def init(self,user_uuid,ase_client,raw_markdown,raw_markdown_prompts,raw_score_prompts,material_id,chapter_name, lesson_name, max_iter = 5, app=None, socketio=None):
self.chapter_chain_now = -1
self.ase_client = ase_client
self.app = app
self.socketio = socketio
@@ -45,7 +59,6 @@ class ChatManager:
self.chapter_name = chapter_name
self.lesson_name = lesson_name
self.chapter_chain = load_chapters(raw_markdown, raw_markdown_prompts, raw_score_prompts)
self.function_manager = FunctionManager()
self.bb = None
self.chat_historys = []
@@ -61,15 +74,16 @@ class ChatManager:
def next_chapter(self):
assert self.chapter_chain_now + 1 < len(self.chapter_chain), "chapter_chain_now out of range"
self.chapter_chain_now += 1
self.bb.next_chapter()
self.focus_chapter(self.chapter_chain_now)
def focus_chapter(self, chapter_index):
assert chapter_index < len(self.chapter_chain), "chapter_index out of range"
self.chapter_chain_now = chapter_index
self.chapter_chain[chapter_index].Focus()
def load_next_chapter(self):
print(f"now load next chapter markdown {self.chapter_chain_now}")
self.ase_client.loadmarkdown(self.chapter_chain[self.chapter_chain_now].chapter, self.chapter_chain[self.chapter_chain_now].chapter_prompt, self.chapter_chain[self.chapter_chain_now].score_prompt)

View File

@@ -28,6 +28,7 @@ class VSCodeNamespace(Namespace):
join_room(user_uuid, namespace='/vscode')
if backboard_manager.get_backboard(user_uuid) == None:
backboard_manager.add_backboard(user_uuid,uuid2username[user_uuid], course_id, lesson_id, path)
def on_message(self, data):
@@ -53,6 +54,7 @@ class AgentNamespace(Namespace):
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"]
@@ -60,8 +62,24 @@ class AgentNamespace(Namespace):
# 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]
user_uuid2ase_client[user_uuid] = HSAEngineClient(current_app.config["ASE_ENGINE_URL"], current_app.config["ASE_ENGINE_NAMESPACE"],id=user_id)
user_uuid2ase_client[user_uuid].connect()
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,
@@ -85,21 +103,13 @@ class AgentNamespace(Namespace):
callback=self.receive_ase_chapter_score,
entry=(get_or_load_current_user(),chatmanager),
init_data={'room': user_uuid}
)
)
user_uuid2ase_client[user_uuid].connect()
fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
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)
user_uuid2ase_client.chatmanager = chatmanager
# 注册函数,以确保一些初始参数
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 = []
join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room
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.focus_chapter(0)
def on_language(self, language):
ex = current_app.extensions
@@ -115,7 +125,7 @@ class AgentNamespace(Namespace):
data = json.loads(data)
if data['type'] == 'text':
res = user_uuid2ase_client[uuid].send_text('dialog', data['data'])
chatmanager.chat_historys.append({'role': 'user', 'content': 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与参数
@@ -125,9 +135,16 @@ class AgentNamespace(Namespace):
d['data'] = res.to_dict()
print("function_call_res", d['data'])
emit(d['route'], d, room=uuid, namespace='/agent')
chatmanager.chat_historys.append({'role': 'user', 'content': data['data']})
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):
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)

View File

@@ -13,7 +13,9 @@ document.addEventListener('DOMContentLoaded', function() {
socket.on('connect', function() {
console.log('Connected to server');
socket.emit('login',JSON.stringify(data));
OpenIframe();
});
socket.on('open-iframe', function(data) {
OpenIframe();
});
// 监听来自服务器的消息
socket.on('message', function(data) {

View File

@@ -0,0 +1,119 @@
<html>
<head>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
</head>
<body class="markdown-body">
<h1>效率的重要性与实践验证</h1>
<h2>效率</h2>
<h3>理论热身:算法选择的智慧</h3>
<h4>任务:分析与决策</h4>
<p>项目组目前有两套备选的交通信号灯同步算法,它们将在不同性能的服务器上运行:</p>
<ul>
<li>
<p><strong>方案A</strong>部署在超级服务器上10^9 次运算/秒采用的是一种较为简单的算法处理n个路口需要 $2n^2$ 次计算。</p>
</li>
<li>
<p><strong>方案B</strong>部署在普通服务器上10^7 次运算/秒但采用的是一种更优化的算法处理n个路口需要 $50nlog_2n$ 次计算。</p>
</li>
</ul>
<p>你的项目经理右侧的Agent希望你通过分析来判断哪个方案更具前景。请与TA对话逐一回答以下问题。</p>
<h4>思考题</h4>
<p>与右侧的Agent对话回答以下问题</p>
<ol>
<li>
<p><strong>概念回顾</strong>:首先,请向你的“经理”解释,根据课程所学,一个合格的“算法”应具备哪些基本特征? </p>
</li>
<li>
<p><strong>小规模测试</strong>对于一个包含100个路口的小型城区n=100计算并说明方案A和方案B分别需要多长时间完成计算在这种情况下你会推荐哪个方案</p>
</li>
<li>
<p><strong>大规模应用</strong>现在我们需要为一座拥有100万个路口的大都市n=1,000,000进行规划。再次计算并说明两个方案的耗时。你的推荐会改变吗为什么</p>
</li>
<li>
<p><strong>总结陈词</strong>:综合以上分析,向你的“经理”总结:为什么一个更优的算法设计,其重要性远超硬件性能的提升? 这验证了课程中提到的哪个核心观点?</p>
</li>
</ol>
<h3>编程实践:验证算法的真实性能</h3>
<h4>任务:编码与分析</h4>
<p>理论分析让你认识到了算法效率的重要性。现在,你需要通过编程来亲身感受不同交通状况对同一算法性能的巨大影响。我们将以“插入排序”为例,来处理三种典型的交通流量数据,这分别对应算法分析中的<strong>最好</strong><strong>最坏</strong><strong>平均</strong>情况。</p>
<h5>题目:模拟交通流量排序</h5>
<p>实现插入排序算法,并验证其在处理“畅通无阻”(数据有序)、“交通大堵塞”(数据逆序)和“随机车流”(数据随机)三种模式时的效率差异。</p>
<h5>代码框架</h5>
<p>在代码编辑区,完成 <code>insertion_sort(arr)</code> 函数的实现后运行完整代码并与Agent讨论结果。
<strong>请创建任意文件,将下面代码写入到编辑器中</strong>
```python
import random
import time</p>
<p>def insertion_sort(arr):
"""
实现插入排序算法
参数arr: 待排序的交通数据数组(整数代表车辆通行次序)
返回: 排序后的数组
"""
# TODO: 请在此处实现你的插入排序逻辑</p>
<p>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</p>
<p>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 # 转换为毫秒</p>
<h1>测试不同规模的路口网络</h1>
<p>network_sizes = [1000, 5000, 10000]
print("交通数据处理算法性能测试:")
for size in network_sizes:
best, worst, avg = generate_traffic_data(size)</p>
<pre><code>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")
</code></pre>
<p>```</p>
<h4>分析与讨论</h4>
<p>完成编程并得到输出后请与右侧Agent讨论以下问题以检验你的理解</p>
<ol>
<li>
<p><strong>结果分析</strong>当网络规模从1000增加到10000时“交通大堵塞”最坏情况的处理时间增长了大约多少倍这更符合O(n)线性还是O(n2)(二次)的增长模式?</p>
</li>
<li>
<p><strong>原因探究</strong>:为什么“畅通无阻”(最好情况)的处理速度如此之快?它的时间复杂度是什么?请结合你的代码逻辑来解释。</p>
</li>
<li>
<p><strong>实践应用</strong>:根据你的实验结果,你认为插入排序是否适合用于需要快速响应大规模交通拥堵的实时预警系统?为什么?</p>
</li>
<li>
<p><strong>融会贯通</strong>:结合第一关的理论分析和第二关的编程实验,你对“算法是解决问题的核心”这句话有了怎样更深的理解?</p>
</li>
</ol>
</body>
</html>

View File

@@ -0,0 +1,126 @@
<html>
<head>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
</head>
<body class="markdown-body">
<h1>算法设计范式:分而治之与归并排序</h1>
<blockquote>
<p>Auto-generated at 2025-09-22 15:38</p>
</blockquote>
<h2>算法设计范式:分而治之与归并排序</h2>
<h3>第一关:理论探究:分而治之的力量</h3>
<p><strong>案例背景:智慧城市交通优化系统</strong></p>
<p>在上周的工作中你已经实现并分析了插入排序在交通数据处理中的性能。虽然它在数据量较小或基本有序的情况下表现不错但在应对大规模拥堵逆序数据其性能瓶颈非常明显。本周你的项目经理Agent将向你介绍一种更高效的算法设计思想——“分而治之”并要求你掌握其代表算法归并排序。</p>
<h4>任务:理解与分析</h4>
<h5>场景介绍</h5>
<p>你的经理告诉你归并排序Merge Sort是解决大规模排序问题的利器。在投入编码之前你必须先从理论上理解它为何如此高效。</p>
<h5>思考题</h5>
<p>请与右侧的Agent你的项目经理对话清晰地回答以下问题以证明你已理解核心思想</p>
<ol>
<li>
<p><strong>分治思想</strong>根据课程资料请解释什么是“分而治之”Divide-and-Conquer设计范式它包含哪三个基本步骤</p>
</li>
<li>
<p><strong>递推关系</strong>:归并排序的时间复杂度可以用递推式 T(n)=2T(n/2)+Θ(n) 来表示。请解释这个式子各部分的含义:</p>
<ul>
<li><code>2</code> 代表什么?</li>
<li><code>T(n/2)</code> 代表什么?</li>
<li><code>Θ(n)</code> 代表什么?</li>
</ul>
</li>
<li>
<p><strong>效率对比</strong>你的同事认为插入排序经过极致优化后处理n个数据的耗时为 $0.1n^2$;而归并排序由于递归和合并开销,耗时为 1000nlog_2n。在处理超大规模城市交通数据时即n趋于无穷大时哪个算法最终会胜出请从渐进增长的角度解释你的理由。</p>
</li>
<li>
<p><strong>增长排序</strong>:将下列函数的渐进增长率从低到高排序,并将它们划分到等价类(即 Θ 关系相同的函数)。这有助于你理解不同算法效率的所在层级。 </p>
<ul>
<li>$n^2$ (插入排序最坏情况)</li>
<li>nlogn (归并排序)</li>
<li>n (一种非常低效的蛮力算法)</li>
<li>$2^n$ (另一种指数级算法)</li>
<li>logn (类似二分查找的效率)</li>
</ul>
</li>
</ol>
<h3>第二关:编程实践:实现归并排序</h3>
<h4>任务:编码与对比</h4>
<h5>场景介绍</h5>
<p>现在你已经从理论上理解了归并排序的威力。是时候亲手实现它,并与上周的插入排序进行一次性能上的正面较量了!</p>
<h5>题目:实现归并排序并对比性能</h5>
<p>你需要实现归并排序的核心函数,并利用上周的测试框架来直观对比它与插入排序在处理不同交通数据时的表现。</p>
<h5>代码框架</h5>
<p>在下方代码编辑区,完成 <code>merge_sort(arr)</code><code>merge(left, right)</code> 两个函数的实现。
```python
import random
import time</p>
<h1>上周实现的插入排序(用于对比)</h1>
<p>def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j &gt;= 0 and arr[j] &gt; key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr</p>
<h1>--- 本周任务:请在下方实现归并排序 ---</h1>
<p>def merge_sort(arr):
"""
实现归并排序算法
参数arr: 待排序的交通数据数组
返回: 一个新的、排序好的数组
"""
# TODO: 实现归并排序的递归逻辑
# 提示当数组元素个数小于等于1时递归终止</p>
<p>def merge(left, right):
"""
合并两个已排序的子数组
参数left: 左侧已排序数组
参数right: 右侧已排序数组
返回: 合并后的一个有序数组
"""</p>
<h1>--- 测试与对比部分 ---</h1>
<p>def measure_performance(sort_func, data):
start_time = time.perf_counter_ns()
sort_func(data.copy())
end_time = time.perf_counter_ns()
return (end_time - start_time) / 10**6</p>
<p>network_sizes = [1000, 5000, 10000, 50000]
print("算法性能对比测试:")
for size in network_sizes:
# 生成逆序数据,这是插入排序的最坏情况
worst_case_data = list(range(size, 0, -1))</p>
<pre><code>time_insertion = measure_performance(insertion_sort, worst_case_data)
time_merge = measure_performance(merge_sort, worst_case_data)
print(f"--- 网络规模 n={size} (最坏情况) ---")
print(f" - 插入排序: {time_insertion:.2f} ms")
print(f" - 归并排序: {time_merge:.2f} ms")
</code></pre>
<p>```</p>
<h5>分析与讨论</h5>
<p>完成编程并得到输出后请与右侧Agent讨论以下问题</p>
<ol>
<li>
<p><strong>性能验证</strong>:观察“交通大堵塞”(最坏情况)的测试结果,归并排序的性能表现与插入排序有何天壤之别?这是否验证了你在第一关的理论分析?</p>
</li>
<li>
<p><strong>性能稳定性</strong>:如果我们将测试数据换成“畅通无阻”(最好情况)或“随机车流”(平均情况),你认为归并排序的运行时间会发生巨大变化吗?为什么?</p>
</li>
<li>
<p><strong>空间成本</strong>:在实现 <code>merge</code> 函数时,你可能创建了一个新的数组 <code>merged</code> 来存放结果。这在算法分析中被称为“空间复杂度”。与在原数组上进行交换的插入排序相比,归并排序的这个特点是优点还是缺点?</p>
</li>
<li>
<p><strong>最终决策</strong>:作为项目工程师,你会选择哪种排序算法用于我们的大规模交通调度系统?请综合考虑<strong>时间效率</strong><strong>空间成本</strong>来陈述你的理由。</p>
</li>
</ol>
</body>
</html>

View File

@@ -102,7 +102,6 @@
<div class="icon" id="toggleButton_icon"></div>
</div>
<script src="/static/js/chatbox.js"></script>
<script>
// 实现左右边栏可拖动
@@ -164,7 +163,14 @@
})
.then(data => {
console.log('Session data:', data);
})
.catch(error => {
console.error('Error fetching session:', error);
});
function OpenIframe(){
// 在成功获取 session 后创建并插入 iframe
const iframe = document.createElement('iframe');
const sessionInfo = data
@@ -174,14 +180,7 @@
// 将 iframe 插入到指定的 div 中
document.getElementById('vscodeWeb').appendChild(iframe);
})
.catch(error => {
console.error('Error fetching session:', error);
});
}
@@ -227,5 +226,7 @@
});
</script>
<script src="/static/js/chatbox.js"></script>
</body>
</html>

View File

@@ -29,9 +29,14 @@
</div>
</main>
<footer>
<p>版权所有 &copy; 2024 “华实伴学君”——教学练评一体的虚拟编码助教</p>
</footer>
<footer>
<p>版权所有 &copy; 2024 “华实伴学君”——教学练评一体的虚拟编码助教</p>
<p>
<a href="https://beian.miit.gov.cn" target="_blank" rel="noopener noreferrer">
沪ICP备2025142149号
</a>
</p>
</footer>
</body>
<script>

View File

@@ -59,6 +59,7 @@ def desktop(user_uuid, course_id, chapter_name, lesson_name):
chatmanager = ChatManager()
print(f"now user uuid {user_uuid}")
current_app.extensions["user_uuid2chatmanager"][user_uuid] = chatmanager
code_server_port = 10000 + int(uuid.uuid4().int % 10000)
# chatmanager.start_code_server(user_uuid, user_id, path_dir, code_server_port)