Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified __pycache__/api_client.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/async_discussion.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/config.cpython-312.pyc
Binary file not shown.
Binary file modified __pycache__/discussion_logic.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/history_manager.cpython-312.pyc
Binary file not shown.
Binary file modified __pycache__/judge_evaluator.cpython-312.pyc
Binary file not shown.
Binary file modified __pycache__/models.cpython-312.pyc
Binary file not shown.
Binary file modified __pycache__/proposal_storage.cpython-312.pyc
Binary file not shown.
76 changes: 76 additions & 0 deletions app.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
2026-04-27 21:03:01,971 - config - INFO - 创建目录: output
2026-04-27 21:03:01,971 - config - INFO - 环境配置检查通过
2026-04-27 21:03:01,972 - config - INFO - 启动Web服务,调试模式: True
2026-04-27 21:03:01,989 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://10.126.25.117:5000
2026-04-27 21:03:01,990 - werkzeug - INFO - Press CTRL+C to quit
2026-04-27 21:03:01,990 - werkzeug - INFO - * Restarting with stat
2026-04-27 21:03:03,089 - config - INFO - 环境配置检查通过
2026-04-27 21:03:03,090 - config - INFO - 启动Web服务,调试模式: True
2026-04-27 21:03:03,101 - werkzeug - WARNING - * Debugger is active!
2026-04-27 21:03:03,110 - werkzeug - INFO - * Debugger PIN: 123-153-070
2026-04-27 21:03:10,430 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:10] "GET / HTTP/1.1" 200 -
2026-04-27 21:03:10,641 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:10] "GET /static/js/app.js HTTP/1.1" 200 -
2026-04-27 21:03:10,642 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:10] "GET /static/css/style.css HTTP/1.1" 200 -
2026-04-27 21:03:12,990 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:12] "GET /api/environment HTTP/1.1" 200 -
2026-04-27 21:03:12,991 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:12] "GET /api/history?limit=20 HTTP/1.1" 200 -
2026-04-27 21:03:13,052 - config - INFO - 客户端连接: UE0nb6hKT0LregjMAAAB
2026-04-27 21:03:13,067 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:13] "GET /favicon.ico HTTP/1.1" 404 -
2026-04-27 21:03:44,818 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:44] "POST /api/discussion/start HTTP/1.1" 200 -
2026-04-27 21:03:44,819 - config - INFO - [Progress] session_start: {"problem": "我想要8月去上海旅游,你推荐去哪里", "max_rounds": 5, "session_file": "output/discussion_session_20260427_210344.json"}
2026-04-27 21:03:44,819 - config - INFO - [Progress] round_start: {"round_num": 1, "phase": "initial_proposals", "message": "第一轮讨论开始:智能体A和B分别生成初始方案"}
2026-04-27 21:03:44,820 - config - INFO - [Progress] agent_thinking: {"agent": "A", "message": "智能体A正在生成初始方案..."}
2026-04-27 21:03:45,499 - config - INFO - [Progress] agent_response: {"agent": "A", "message": "智能体A已完成方案"}
2026-04-27 21:03:45,500 - config - INFO - [Progress] agent_thinking: {"agent": "B", "message": "智能体B正在生成初始方案..."}
2026-04-27 21:03:45,501 - config - INFO - [Progress] round_complete: {"round_num": 1, "phase": "initial_proposals", "proposals": {"A": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "B": "错误: 'ascii' codec can't encode characters in position 7-11: ordinal not in range(128)"}}
2026-04-27 21:03:45,501 - config - INFO - [Progress] round_start: {"round_num": 2, "phase": "integration", "message": "第2轮讨论开始:智能体互相整合方案"}
2026-04-27 21:03:45,501 - config - INFO - [Progress] agent_thinking: {"agent": "A", "message": "智能体A正在整合B的方案..."}
2026-04-27 21:03:45,960 - config - INFO - [Progress] agent_response: {"agent": "A", "message": "智能体A已完成整合"}
2026-04-27 21:03:45,960 - config - INFO - [Progress] agent_thinking: {"agent": "B", "message": "智能体B正在整合A的方案..."}
2026-04-27 21:03:45,960 - config - INFO - [Progress] judge_start: {"round_num": 2, "message": "裁判开始评估方案"}
2026-04-27 21:03:46,222 - config - INFO - [Progress] judge_complete: {"round_num": 2, "a_score": 0, "b_score": 0, "best_score": 0, "reason": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "judge_evaluation": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)"}
2026-04-27 21:03:46,223 - config - INFO - [Progress] round_complete: {"round_num": 2, "phase": "complete", "proposals": {"A": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "B": "错误: 'ascii' codec can't encode characters in position 7-11: ordinal not in range(128)"}, "scores": {"A": 0, "B": 0}}
2026-04-27 21:03:46,225 - config - INFO - [Progress] round_start: {"round_num": 3, "phase": "integration", "message": "第3轮讨论开始:智能体互相整合方案"}
2026-04-27 21:03:46,225 - config - INFO - [Progress] agent_thinking: {"agent": "A", "message": "智能体A正在整合B的方案..."}
2026-04-27 21:03:46,660 - config - INFO - [Progress] agent_response: {"agent": "A", "message": "智能体A已完成整合"}
2026-04-27 21:03:46,661 - config - INFO - [Progress] agent_thinking: {"agent": "B", "message": "智能体B正在整合A的方案..."}
2026-04-27 21:03:46,661 - config - INFO - [Progress] judge_start: {"round_num": 3, "message": "裁判开始评估方案"}
2026-04-27 21:03:46,879 - config - INFO - [Progress] judge_complete: {"round_num": 3, "a_score": 0, "b_score": 0, "best_score": 0, "reason": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "judge_evaluation": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)"}
2026-04-27 21:03:46,881 - config - INFO - [Progress] round_complete: {"round_num": 3, "phase": "complete", "proposals": {"A": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "B": "错误: 'ascii' codec can't encode characters in position 7-11: ordinal not in range(128)"}, "scores": {"A": 0, "B": 0}}
2026-04-27 21:03:46,882 - config - INFO - [Progress] round_start: {"round_num": 4, "phase": "integration", "message": "第4轮讨论开始:智能体互相整合方案"}
2026-04-27 21:03:46,882 - config - INFO - [Progress] agent_thinking: {"agent": "A", "message": "智能体A正在整合B的方案..."}
2026-04-27 21:03:47,304 - config - INFO - [Progress] agent_response: {"agent": "A", "message": "智能体A已完成整合"}
2026-04-27 21:03:47,305 - config - INFO - [Progress] agent_thinking: {"agent": "B", "message": "智能体B正在整合A的方案..."}
2026-04-27 21:03:47,305 - config - INFO - [Progress] judge_start: {"round_num": 4, "message": "裁判开始评估方案"}
2026-04-27 21:03:47,520 - config - INFO - [Progress] judge_complete: {"round_num": 4, "a_score": 0, "b_score": 0, "best_score": 0, "reason": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "judge_evaluation": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)"}
2026-04-27 21:03:47,521 - config - INFO - [Progress] round_complete: {"round_num": 4, "phase": "complete", "proposals": {"A": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "B": "错误: 'ascii' codec can't encode characters in position 7-11: ordinal not in range(128)"}, "scores": {"A": 0, "B": 0}}
2026-04-27 21:03:47,521 - config - INFO - [Progress] round_start: {"round_num": 5, "phase": "integration", "message": "第5轮讨论开始:智能体互相整合方案"}
2026-04-27 21:03:47,521 - config - INFO - [Progress] agent_thinking: {"agent": "A", "message": "智能体A正在整合B的方案..."}
2026-04-27 21:03:48,594 - config - INFO - [Progress] agent_response: {"agent": "A", "message": "智能体A已完成整合"}
2026-04-27 21:03:48,594 - config - INFO - [Progress] agent_thinking: {"agent": "B", "message": "智能体B正在整合A的方案..."}
2026-04-27 21:03:48,596 - config - INFO - [Progress] judge_start: {"round_num": 5, "message": "裁判开始评估方案"}
2026-04-27 21:03:49,118 - config - INFO - [Progress] judge_complete: {"round_num": 5, "a_score": 0, "b_score": 0, "best_score": 0, "reason": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "judge_evaluation": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)"}
2026-04-27 21:03:49,164 - config - INFO - [Progress] round_complete: {"round_num": 5, "phase": "complete", "proposals": {"A": "错误: 'ascii' codec can't encode characters in position 7-15: ordinal not in range(128)", "B": "错误: 'ascii' codec can't encode characters in position 7-11: ordinal not in range(128)"}, "scores": {"A": 0, "B": 0}}
2026-04-27 21:03:49,167 - config - INFO - [Progress] selecting_best: {"message": "已达最大轮数,选择最优方案"}
2026-04-27 21:03:49,173 - config - INFO - [Progress] discussion_complete: {"status": "completed", "problem": "我想要8月去上海旅游,你推荐去哪里", "total_rounds": 5, "best_score": 0, "best_solution": "", "session_file": "output/discussion_session_20260427_210344.json", "rounds": [{"round_num": 1, "a_score": null, "b_score": null, "has_judge": false}, {"round_num": 2, "a_score": 0, "b_score": 0, "has_judge": true}, {"round_num": 3, "a_score": 0, "b_score": 0, "has_judge": true}, {"round_num": 4, "a_score": 0, "b_score": 0, "has_judge": true}, {"round_num": 5, "a_score": 0, "b_score": 0, "has_judge": true}]}
2026-04-27 21:03:49,192 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:49] "GET /api/history?limit=20 HTTP/1.1" 200 -
2026-04-27 21:03:54,885 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:54] "GET /static/css/style.css HTTP/1.1" 304 -
2026-04-27 21:03:54,899 - werkzeug - INFO - 127.0.0.1 - - [27/Apr/2026 21:03:54] "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 -
2026-04-27 21:06:33,541 - werkzeug - INFO - * Detected change in 'E:\\tests\\Multi-agent-discussion-\\config.py', reloading
2026-04-27 21:06:33,736 - werkzeug - INFO - * Restarting with stat
2026-04-27 21:06:34 - root - INFO - 环境配置检查通过
2026-04-27 21:06:34 - root - INFO - 启动Web服务,调试模式: True
2026-04-27 21:06:34 - werkzeug - WARNING - * Debugger is active!
2026-04-27 21:06:34 - werkzeug - INFO - * Debugger PIN: 123-153-070
2026-04-27 21:06:35 - root - INFO - 客户端连接: J-zZYT0QfCI3i1KtAAAB
2026-04-27 21:06:52 - werkzeug - INFO - * Detected change in 'E:\\tests\\Multi-agent-discussion-\\app.py', reloading
2026-04-27 21:06:52,202 - werkzeug - INFO - * Restarting with stat
2026-04-27 21:06:53 - root - INFO - 环境配置检查通过
2026-04-27 21:06:53 - root - INFO - 启动Web服务,调试模式: True
2026-04-27 21:06:53 - werkzeug - WARNING - * Debugger is active!
2026-04-27 21:06:53 - werkzeug - INFO - * Debugger PIN: 123-153-070
2026-04-27 21:06:53 - root - INFO - 客户端连接: 7GK83iIFs3rJXO20AAAB
2026-04-27 21:07:22 - werkzeug - INFO - * Detected change in 'E:\\tests\\Multi-agent-discussion-\\app.py', reloading
2026-04-27 21:07:22,646 - werkzeug - INFO - * Restarting with stat
252 changes: 252 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
# -*- coding: utf-8 -*-
import sys
import os

if sys.platform == 'win32':
os.environ['PYTHONIOENCODING'] = 'utf-8'
import codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, errors='replace')
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, errors='replace')

from config import Config, logger

import asyncio
import json
from threading import Thread
from flask import Flask, render_template, jsonify, request, send_file, Response
from flask_cors import CORS
from flask_socketio import SocketIO, emit
from datetime import datetime
from async_discussion import AsyncDiscussionManager
from history_manager import HistoryManager

app = Flask(__name__,
static_folder='static',
template_folder='templates')
app.config.from_object(Config)

CORS(app, resources={r"/api/*": {"origins": "*"}})
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')

discussion_manager: AsyncDiscussionManager = None
history_manager = HistoryManager()

active_discussions = {}


def progress_callback(event_data):
socketio.emit('discussion_update', event_data)


@app.route('/')
def index():
return render_template('index.html')


@app.route('/api/status')
def get_status():
env_status = Config.check_environment()
return jsonify({
"status": env_status["status"],
"environment": env_status["config"],
"errors": env_status["errors"],
"warnings": env_status["warnings"]
})


@app.route('/api/environment', methods=['GET'])
def get_environment():
env_status = Config.check_environment()
return jsonify(env_status)


@app.route('/api/discussion/start', methods=['POST'])
def start_discussion():
global discussion_manager

data = request.get_json()
problem = data.get('problem', '')
max_rounds = data.get('max_rounds', Config.MAX_ROUNDS)

if not problem.strip():
return jsonify({"error": "请输入讨论问题"}), 400

env_status = Config.check_environment()
if len(env_status["errors"]) > 0:
return jsonify({
"error": "环境配置错误",
"details": env_status["errors"]
}), 400

discussion_manager = AsyncDiscussionManager(on_progress_callback=progress_callback)

def run_discussion():
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(
discussion_manager.start_discussion(problem, max_rounds)
)
loop.close()
except Exception as e:
logger.error(f"讨论线程出错: {str(e)}", exc_info=True)
socketio.emit('discussion_error', {"message": str(e)})

thread = Thread(target=run_discussion, daemon=True)
thread.start()

return jsonify({
"status": "started",
"message": "讨论已开始",
"problem": problem,
"max_rounds": max_rounds
})


@app.route('/api/discussion/stop', methods=['POST'])
def stop_discussion():
global discussion_manager

if not discussion_manager or not discussion_manager.is_running:
return jsonify({"error": "没有正在进行的讨论"}), 400

discussion_manager.stop_discussion()

return jsonify({
"status": "stopped",
"message": "讨论已停止"
})


@app.route('/api/discussion/current')
def get_current_discussion():
global discussion_manager

if not discussion_manager:
return jsonify({"session": None})

session = discussion_manager.get_current_session()
return jsonify({"session": session})


@app.route('/api/history')
def get_history():
limit = request.args.get('limit', type=int)
sessions = history_manager.list_all_sessions(limit=limit)
return jsonify({
"sessions": sessions,
"total": len(sessions)
})


@app.route('/api/history/<filename>')
def get_history_session(filename):
session = history_manager.get_session(filename)
if not session:
return jsonify({"error": "会话不存在"}), 404

return jsonify(session)


@app.route('/api/history/<filename>/delete', methods=['DELETE'])
def delete_history_session(filename):
success = history_manager.delete_session(filename)
if not success:
return jsonify({"error": "删除失败"}), 400

return jsonify({"status": "deleted", "message": "会话已删除"})


@app.route('/api/history/<filename>/export')
def export_history_session(filename):
markdown = history_manager.export_session_to_markdown(filename)
if not markdown:
return jsonify({"error": "导出失败"}), 400

timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
export_filename = f"discussion_report_{timestamp}.md"

return Response(
markdown,
mimetype='text/markdown',
headers={
'Content-Disposition': f'attachment; filename="{export_filename}"'
}
)


@app.route('/api/history/<filename>/download')
def download_history_session(filename):
session = history_manager.get_session(filename)
if not session:
return jsonify({"error": "文件不存在"}), 404

filepath = os.path.join(Config.OUTPUT_DIR, filename)
if not os.path.exists(filepath):
filepath = filename
if not os.path.exists(filepath):
return jsonify({"error": "文件不存在"}), 404

return send_file(
filepath,
mimetype='application/json',
as_attachment=True,
download_name=filename
)


@app.route('/api/statistics')
def get_statistics():
stats = history_manager.get_statistics()
return jsonify(stats)


@socketio.on('connect')
def handle_connect():
logger.info(f"客户端连接: {request.sid}")
emit('connected', {"status": "ok", "sid": request.sid})


@socketio.on('disconnect')
def handle_disconnect():
logger.info(f"客户端断开连接: {request.sid}")


@socketio.on('ping')
def handle_ping():
emit('pong', {"timestamp": datetime.now().isoformat()})


def ensure_directories():
dirs = [
Config.OUTPUT_DIR,
'static',
'static/css',
'static/js',
'templates'
]
for d in dirs:
if not os.path.exists(d):
os.makedirs(d, exist_ok=True)
logger.info(f"创建目录: {d}")


if __name__ == '__main__':
ensure_directories()

env_status = Config.check_environment()
if len(env_status["errors"]) > 0:
logger.warning("环境配置存在错误:")
for error in env_status["errors"]:
logger.warning(f" - {error}")
else:
logger.info("环境配置检查通过")

logger.info(f"启动Web服务,调试模式: {Config.DEBUG}")
socketio.run(
app,
host='0.0.0.0',
port=5000,
debug=Config.DEBUG,
allow_unsafe_werkzeug=True
)
Loading