diff --git a/Html/__pycache__/backboardManager.cpython-310.pyc b/Html/__pycache__/backboardManager.cpython-310.pyc
index 876200f..1e7d73f 100644
Binary files a/Html/__pycache__/backboardManager.cpython-310.pyc and b/Html/__pycache__/backboardManager.cpython-310.pyc differ
diff --git a/Html/apps/config.py b/Html/apps/config.py
index cc61509..df4ad86 100644
--- a/Html/apps/config.py
+++ b/Html/apps/config.py
@@ -44,4 +44,7 @@ class Config:
"secret_key": GLOBAL_CONFIG['TENCENT_COS']['secret_key'],
"bucket": GLOBAL_CONFIG['TENCENT_COS']['bucket'],
"region": GLOBAL_CONFIG['TENCENT_COS']['region'],
- }
\ No newline at end of file
+ }
+
+ ASE_ENGINE_URL = GLOBAL_CONFIG['ASE_ENGINE']['url']
+ ASE_ENGINE_NAMESPACE = GLOBAL_CONFIG['ASE_ENGINE']['namespace']
\ No newline at end of file
diff --git a/Html/apps/extension_ase/ase_client/__init__.py b/Html/apps/extension_ase/ase_client/__init__.py
new file mode 100644
index 0000000..80bdad0
--- /dev/null
+++ b/Html/apps/extension_ase/ase_client/__init__.py
@@ -0,0 +1 @@
+from .client import ASEngineClient
\ No newline at end of file
diff --git a/Html/apps/extension_ase/ase_client/client.py b/Html/apps/extension_ase/ase_client/client.py
new file mode 100644
index 0000000..140c0c2
--- /dev/null
+++ b/Html/apps/extension_ase/ase_client/client.py
@@ -0,0 +1,267 @@
+import socketio
+import socketio
+import time
+import base64
+import os
+from datetime import datetime
+from typing import Dict, Callable, Any, Optional
+from functools import partial
+
+class ASEngineClient:
+ def __init__(self, server_url: str, namespace: str):
+ """
+ 初始化客户端
+ :param server_url: 服务器URL,例如 'http://localhost:5000'
+ :param namespace: 命名空间,例如 '/socket.io/7100eebf7a909e1ee3f4e06766f512f0358ecb6ac51d5434c17d31dd70890dc1'
+ """
+ self.server_url = server_url
+ self.namespace = namespace
+ self.sid = None
+ self.connected = False
+
+ # 创建SocketIO客户端
+ self.sio = socketio.Client()
+
+ # 存储路由和对应的回调函数
+ self.routes: Dict[str, Dict[str, Callable]] = {}
+
+ # 注册基础事件处理函数
+ self._register_base_events()
+
+ def _register_base_events(self):
+ """注册基础事件处理函数"""
+ # 连接事件
+ @self.sio.on('connect', namespace=self.namespace)
+ def on_connect():
+ self.connected = True
+ self.sid = self.sio.get_sid(namespace=self.namespace)
+ print(f"Connected to server. SID: {self.sid}")
+
+ # 断开连接事件
+ @self.sio.on('disconnect', namespace=self.namespace)
+ def on_disconnect():
+ self.connected = False
+ self.sid = None
+ print("Disconnected from server")
+
+ @self.sio.on('error', namespace=self.namespace)
+ def on_error(data):
+ print(f"Received error: {data}")
+ self.connected = False
+ self.sid = None
+
+
+ # 响应事件
+ @self.sio.on('response', namespace=self.namespace)
+ def on_response(data):
+ print(f"Received response: {data}")
+
+
+
+
+ def register_route_with_entry(self, route: str,
+ callback: Optional[Callable] = None,
+ entry: Any = None,
+ init_data: Optional[Any] = None) -> bool:
+ if not route:
+ print("Route cannot be empty")
+ return False
+
+ if callback is None:
+ bound_cb = self._default_callback
+ else:
+ bound_cb = partial(callback, entry) # 等价于 lambda data, init: callback(entry, data, init)
+
+ self.routes[route] = {
+ 'callback': bound_cb,
+ 'entry': entry,
+ 'init_data': init_data,
+ }
+
+ @self.sio.on(route, namespace=self.namespace)
+ def on_route_message(data, _route=route):
+ print(f"Received message on route '{_route}': {data}")
+ route_info = self.routes.get(_route)
+ if not route_info:
+ return
+ cb = route_info['callback'] # 已经绑定过 entry
+ init = route_info.get('init_data')
+ try:
+ cb(data, init) # 现在只传 data / init_data
+ except Exception as e:
+ print(f"Callback error on route '{_route}': {e}")
+
+ return True
+
+
+ def register_route(self, route: str, callback: Optional[Callable] = None, init_data: Optional[Any] = None):
+ """
+ 注册一个路由及其回调函数
+ :param route: 路由名称
+ :param callback: 回调函数,接收消息数据作为参数
+ :return: 是否注册成功
+ """
+ if not route:
+ print("Route cannot be empty")
+ return False
+
+ # 存储路由和回调
+ self.routes[route] = {
+ 'callback': callback if callback else self._default_callback
+ }
+
+ # 注册事件处理器
+ @self.sio.on(route, namespace=self.namespace)
+ def on_route_message(data):
+ print(f"Received message on route '{route}': {data}")
+ if 'callback' in self.routes[route]:
+ try:
+ self.routes[route]['callback'](None, data, init_data)
+ except Exception as e:
+ print(f"Error in callback for route '{route}': {e}")
+
+ print(f"Route '{route}' registered successfully")
+ return True
+
+ def _default_callback(self, entry: Any, data: Any, init_data: Optional[Any] = None):
+ """默认回调函数"""
+ print(f"Default callback received: {data}")
+
+ def connect(self, timeout: int = 5) -> bool:
+ """
+ 连接到服务器
+ :param timeout: 超时时间(秒)
+ :return: 是否连接成功
+ """
+ try:
+ self.sio.connect(
+ self.server_url,
+ namespaces=[self.namespace],
+ wait_timeout=timeout
+ )
+ # 等待连接建立
+ start_time = time.time()
+ while not self.connected and (time.time() - start_time) < timeout:
+ time.sleep(0.1)
+ return self.connected
+ except Exception as e:
+ print(f"Connection failed: {e}")
+ return False
+
+ def disconnect(self):
+ """断开与服务器的连接"""
+ if self.connected:
+ self.sio.disconnect()
+ self.connected = False
+ self.sid = None
+ print("Disconnected from server")
+
+ def send_text(self, route: str, text: str) -> bool:
+ """
+ 发送文本消息
+ :param route: 目标路由
+ :param text: 要发送的文本
+ :return: 是否发送成功
+ """
+ if not self.connected:
+ print("Not connected to server")
+ return False
+
+ if route not in self.routes:
+ print(f"Route '{route}' not registered")
+ return False
+
+ try:
+ self.sio.emit(route, {'type': 'text', 'data': text}, namespace=self.namespace)
+ print(f"Sent text to route '{route}': {text}")
+ return True
+ except Exception as e:
+ print(f"Failed to send text to route '{route}': {e}")
+ return False
+
+ def send_voice(self, route: str, voice_data: bytes) -> bool:
+ """
+ 发送语音数据
+ :param route: 目标路由
+ :param voice_data: 语音数据字节流
+ :return: 是否发送成功
+ """
+ if not self.connected:
+ print("Not connected to server")
+ return False
+
+ try:
+ # 编码语音数据为base64
+ # voice_data = 'data:image/jpeg;base64,' +base64.b64encode(voice_data).decode('utf-8')
+
+ # 发送数据
+ self.sio.emit(
+ route,
+ {
+ 'type': 'audio',
+ 'data': voice_data,
+ 'timestamp': int(time.time() * 1000),
+ 'sampleRate': 16000
+ },
+ namespace=self.namespace
+ )
+
+
+ print(f"Sent voice file to route '{route}'")
+ return True
+ except Exception as e:
+ print(f"Failed to send voice to route '{route}': {e}")
+ return False
+
+ def send_image(self, route: str, file_path: str) -> bool:
+ """
+ 发送图片文件
+ :param route: 目标路由
+ :param file_path: 图片文件路径
+ :return: 是否发送成功
+ """
+ if not self.connected:
+ print("Not connected to server")
+ return False
+
+
+ try:
+ # 检查文件是否存在
+ if not os.path.exists(file_path):
+ print(f"File not found: {file_path}")
+ return False
+
+ # 读取文件并进行base64编码
+ with open(file_path, 'rb') as f:
+ image_data = 'data:image/jpeg;base64,' + base64.b64encode(f.read()).decode('utf-8')
+
+ # 获取文件名
+ filename = os.path.basename(file_path)
+
+ # 发送数据
+ self.sio.emit(
+ route,
+ {
+ 'type': 'image',
+ 'data': image_data
+ },
+ namespace=self.namespace
+ )
+ print(f"Sent image file to route '{route}': {filename}")
+ return True
+ except Exception as e:
+ print(f"Failed to send image to route '{route}': {e}")
+ return False
+
+ def run_forever(self):
+ """
+ 保持客户端运行"""
+ if self.connected:
+ try:
+ while True:
+ time.sleep(1)
+ except KeyboardInterrupt:
+ print("Client stopped by user")
+ self.disconnect()
+ else:
+ print("Not connected to server")
\ No newline at end of file
diff --git a/Html/apps/extensions.py b/Html/apps/extensions.py
index bb0bc58..300203e 100644
--- a/Html/apps/extensions.py
+++ b/Html/apps/extensions.py
@@ -13,7 +13,7 @@ from qcloud_cos import CosS3Client
mongo = PyMongo()
-socketio = SocketIO(cors_allowed_origins="*") # 不直接传 app
+socketio = SocketIO(cors_allowed_origins="*",max_payload_size=52428800, async_mode="threading") # 不直接传 app
cors = CORS()
# ===== 你的全局对象 =====
# Backboard
@@ -28,6 +28,8 @@ username2uuid = {}
course_list = CourseList()
user_uuid2UserClass = {}
+user_uuid2ase_client = {}
+
from AlgoriAgent.projects.algoriAgent.agent_manager import AgentManager
agent_manager = AgentManager()
def init_extensions(app):
@@ -37,6 +39,7 @@ def init_extensions(app):
cors_allowed_origins='*',#app.config["VSCODE_WEB_URL"],
ping_timeout=app.config["SOCKETIO_PING_TIMEOUT"],
ping_interval=app.config["SOCKETIO_PING_INTERVAL"],
+ max_payload_size=50000000, async_mode="threading"
)
cors.init_app(
app,
@@ -55,7 +58,7 @@ def init_extensions(app):
app.extensions["user_uuid2UserClass"] = user_uuid2UserClass
app.extensions["agent_manager"] = agent_manager
app.extensions["my_function"] = MyFunction()
-
+ app.extensions["user_uuid2ase_client"] = user_uuid2ase_client
mongo.init_app(app,uri=app.config["MONGO_URI"])
app.extensions["mongo"] = mongo
diff --git a/Html/apps/sockets/namespaces.py b/Html/apps/sockets/namespaces.py
index 6480fbf..f0c8146 100644
--- a/Html/apps/sockets/namespaces.py
+++ b/Html/apps/sockets/namespaces.py
@@ -5,6 +5,7 @@ from flask_socketio import Namespace, join_room, leave_room, emit
from ..services.memory_service import save_chapter_memory_by_uuid
from ..services.backboard_service import realtime_response
from ..services.markdown_service import load_full_markdown_file
+from ..extension_ase.ase_client import ASEngineClient
class VSCodeNamespace(Namespace):
def on_login(self,data):
@@ -36,6 +37,7 @@ class VSCodeNamespace(Namespace):
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"]
@@ -48,6 +50,15 @@ class AgentNamespace(Namespace):
user_id = uuid2username[user_uuid]
session['user_uuid'] = user_uuid
print(f'User connected with session user_uuid: {user_uuid}')
+ user_uuid2ase_client = ex["user_uuid2ase_client"]
+ user_uuid2ase_client[user_uuid] = ASEngineClient(current_app.config["ASE_ENGINE_URL"], current_app.config["ASE_ENGINE_NAMESPACE"])
+ user_uuid2ase_client[user_uuid].connect()
+ user_uuid2ase_client[user_uuid].register_route_with_entry(
+ route='dialog',
+ callback=self.receive_ase_dialog,
+ entry=self, # 传你的 Namespace 对象
+ init_data={'room': user_uuid} # 想传啥都可以
+ )
fmd,fmdp,fsp = load_full_markdown_file(course_id, chapter_name, lesson_name)
# 从markdown、markdown_prompts、score_prompts中各读取数据folder.md并进行new_agent
@@ -74,31 +85,40 @@ class AgentNamespace(Namespace):
uuid = session.get('user_uuid')
uuid2username = ex["uuid2username"]
user_id = uuid2username[uuid]
+ user_uuid2ase_client = ex["user_uuid2ase_client"]
if (type(data)==str):
data = json.loads(data)
if data['type'] == 'text':
- res = agent_manager.invoke(uuid, data['data'], backboard_manager.get_backboard(user_id).get_info_prompt())
- print('=*='*20)
- print(res.content)
- reply = f"{res.content['speak']}"
- with current_app.app_context():
- emit('message',reply, room=uuid, namespace='/agent')
- emit('request_function',res.content['function'], room=uuid, namespace='/agent')
+ # res = agent_manager.invoke(uuid, data['data'], backboard_manager.get_backboard(uuid).get_info_prompt())
+ user_uuid2ase_client[uuid].send_text('dialog', data['data'])
+ # print('=*='*20)
+ # print(res.content)
+ # reply = f"{res.content['speak']}"
+ # with current_app.app_context():
+ # emit('message',reply, room=uuid, namespace='/agent')
+ # emit('request_function',res.content['function'], room=uuid, namespace='/agent')
if data['type'] == 'function':
agent_manager.function_call(uuid, data['data'])
+
+ def receive_ase_dialog(client_entry: ASEngineClient, namespace_entry: Namespace, data, init_data):
+ print(f"Received from ASEngine: {data}")
+ # 直接使用 entry(也就是你的 Namespace 对象)
+ namespace_entry.emit('message', data['data'], room=init_data['room'], namespace='/agent')
+
+
+
def on_initiative(self,data):
print("User active function call")
ex = current_app.extensions
agent_manager = ex["agent_manager"]
backboard_manager = ex["backboard_manager"]
- uuid2username = ex["uuid2username"]
- user_id = uuid2username[session['user_uuid']]
+ uuid = session.get('user_uuid')
if data['name'] == 'sample_judge':
- agent_manager.sample_judge(user_id, backboard_manager.get_backboard(user_id))
+ agent_manager.sample_judge(uuid, backboard_manager.get_backboard(uuid))
if data['name'] == 'judge':
- agent_manager.judge(user_id, backboard_manager.get_backboard(user_id))
+ agent_manager.judge(uuid, backboard_manager.get_backboard(uuid))
diff --git a/Html/backboardManager.py b/Html/backboardManager.py
index 1777f8d..7de5f19 100644
--- a/Html/backboardManager.py
+++ b/Html/backboardManager.py
@@ -5,8 +5,8 @@ import time
import os
class Backboard:
- def __init__(self, user_id, username, course_id, lesson_id, root_path):
- self.user_id = user_id
+ def __init__(self, user_uuid, username, course_id, lesson_id, root_path):
+ self.user_uuid = user_uuid
self.username = username
self.course_id = course_id
self.lesson_id = lesson_id
@@ -68,13 +68,13 @@ class Backboard:
class BackBoardManager:
def __init__(self):
- self.backboards = {} # user_id: Backboard
+ self.backboards = {} # user_uuid: Backboard
- def add_backboard(self, user_id, username, course_id, lesson_id, root_path):
- self.backboards[user_id] = Backboard(user_id,username, course_id, lesson_id, root_path)
+ def add_backboard(self, user_uuid, username, course_id, lesson_id, root_path):
+ self.backboards[user_uuid] = Backboard(user_uuid,username, course_id, lesson_id, root_path)
- def get_backboard(self, user_id) -> Backboard:
- return self.backboards[user_id]
+ def get_backboard(self, user_uuid) -> Backboard:
+ return self.backboards[user_uuid]
diff --git a/study/TCake/68bacdfadf5aeae0912f7f18/基础算法/.config b/study/TCake/68bacdfadf5aeae0912f7f18/基础算法/.config
index fc40984..6455270 100644
--- a/study/TCake/68bacdfadf5aeae0912f7f18/基础算法/.config
+++ b/study/TCake/68bacdfadf5aeae0912f7f18/基础算法/.config
@@ -1 +1 @@
-{"user_uuid": "user_ec2c74c2-9466-4ea1-99ae-15c2ea3f8c8e", "course_id": "68bacdfadf5aeae0912f7f18", "chapter_name": "基础算法", "lesson_name": "二分", "path": "/mnt/f/GIThubRepository/CodeAgent/code-agent/study/TCake/68bacdfadf5aeae0912f7f18/基础算法"}
\ No newline at end of file
+{"user_uuid": "user_d0cb8736-c5b0-42ba-8eca-6dc9754d9645", "course_id": "68bacdfadf5aeae0912f7f18", "chapter_name": "基础算法", "lesson_name": "二分", "path": "/mnt/f/GIThubRepository/CodeAgent/code-agent/study/TCake/68bacdfadf5aeae0912f7f18/基础算法"}
\ No newline at end of file