核心组件: - Orchestrator: 意图理解、任务拆分、竞标管理、结果验证 - Worker: 竞标任务、执行交付 - TaskBoard: 状态管理、信息存储 - BidEvaluator: 竞标评估算法 - ExecutionMonitor: 执行监控、超时处理 - LLMClient: 大模型接口调用 功能特性: - 竞标机制:Agent主动竞争任务 - 动态调度:串行/并行任务智能调度 - 智能容错:超时切换、验证重试 - 质量保证:结果验证、历史追踪 Web界面:首页、请求列表、任务列表、Agent管理 API接口:请求/任务/Agent管理、测试接口 端口:19015
279 lines
11 KiB
HTML
279 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>多智能体竞标调度系统</title>
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
|
||
<style>
|
||
body { background-color: #f5f7fa; }
|
||
.hero-section {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 60px 0;
|
||
}
|
||
.stat-card {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||
}
|
||
.feature-card {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||
transition: transform 0.2s;
|
||
}
|
||
.feature-card:hover {
|
||
transform: translateY(-5px);
|
||
}
|
||
.input-area {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||
}
|
||
.result-area {
|
||
background: #1a1a2e;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
color: #eee;
|
||
min-height: 300px;
|
||
}
|
||
.agent-badge {
|
||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||
color: white;
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
font-size: 0.85rem;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||
<div class="container">
|
||
<a class="navbar-brand" href="/">
|
||
<i class="ri-robot-2-line"></i> 多智能体竞标调度系统
|
||
</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarNav">
|
||
<ul class="navbar-nav ms-auto">
|
||
<li class="nav-item"><a class="nav-link active" href="/">首页</a></li>
|
||
<li class="nav-item"><a class="nav-link" href="/requests">请求列表</a></li>
|
||
<li class="nav-item"><a class="nav-link" href="/tasks">任务列表</a></li>
|
||
<li class="nav-item"><a class="nav-link" href="/agents">Agent管理</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="hero-section">
|
||
<div class="container text-center">
|
||
<h1 class="display-4"><i class="ri-robot-2-fill"></i> 多智能体竞标调度系统</h1>
|
||
<p class="lead">任务竞标 · 动态调度 · 智能容错</p>
|
||
<div class="mt-4">
|
||
<span class="agent-badge me-2"><i class="ri-code-line"></i> 代码专家</span>
|
||
<span class="agent-badge me-2"><i class="ri-search-line"></i> 搜索专家</span>
|
||
<span class="agent-badge me-2"><i class="ri-edit-line"></i> 写作专家</span>
|
||
<span class="agent-badge"><i class="ri-bar-chart-line"></i> 分析专家</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container py-4">
|
||
<!-- 统计卡片 -->
|
||
<div class="row mb-4">
|
||
<div class="col-md-3">
|
||
<div class="stat-card text-center">
|
||
<i class="ri-message-3-line fs-1 text-primary"></i>
|
||
<h3 id="stat-requests">0</h3>
|
||
<p class="text-muted">用户请求</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="stat-card text-center">
|
||
<i class="ri-task-line fs-1 text-success"></i>
|
||
<h3 id="stat-tasks">0</h3>
|
||
<p class="text-muted">任务总数</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="stat-card text-center">
|
||
<i class="ri-robot-line fs-1 text-warning"></i>
|
||
<h3 id="stat-agents">4</h3>
|
||
<p class="text-muted">注册Agent</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="stat-card text-center">
|
||
<i class="ri-flashlight-line fs-1 text-danger"></i>
|
||
<h3 id="stat-active">0</h3>
|
||
<p class="text-muted">活跃执行</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 输入区域 -->
|
||
<div class="row mb-4">
|
||
<div class="col-md-6">
|
||
<div class="input-area">
|
||
<h5><i class="ri-chat-3-line"></i> 发送请求</h5>
|
||
<div class="mb-3">
|
||
<textarea id="user-input" class="form-control" rows="5"
|
||
placeholder="输入你的请求,例如:帮我写一个Python爬虫,爬取新闻网站..."></textarea>
|
||
</div>
|
||
<button id="submit-btn" class="btn btn-primary w-100">
|
||
<i class="ri-send-plane-fill"></i> 发送请求
|
||
</button>
|
||
|
||
<div class="mt-3">
|
||
<h6>快速测试:</h6>
|
||
<button class="btn btn-outline-secondary btn-sm me-2" onclick="quickTest('intent')">意图分析</button>
|
||
<button class="btn btn-outline-secondary btn-sm me-2" onclick="quickTest('split')">任务拆分</button>
|
||
<button class="btn btn-outline-secondary btn-sm" onclick="quickTest('full')">完整流程</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="result-area">
|
||
<h6><i class="ri-terminal-line"></i> 执行日志</h6>
|
||
<div id="log-output" style="font-family: monospace; white-space: pre-wrap; max-height: 280px; overflow-y: auto;">
|
||
等待输入...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 功能介绍 -->
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<div class="feature-card">
|
||
<i class="ri-award-line fs-1 text-primary"></i>
|
||
<h5 class="mt-3">竞标机制</h5>
|
||
<p>Agent主动竞争任务,展示能力和方案,规划Agent综合评估选择最佳执行者。</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<div class="feature-card">
|
||
<i class="ri-flow-chart fs-1 text-success"></i>
|
||
<h5 class="mt-3">动态调度</h5>
|
||
<p>串行任务严格按依赖执行,并行任务最大化并发,智能分配执行顺序。</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<div class="feature-card">
|
||
<i class="ri-shield-check-line fs-1 text-warning"></i>
|
||
<h5 class="mt-3">智能容错</h5>
|
||
<p>超时自动切换备选Agent,验证失败给予重试机会,失败记录用于改进。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||
<script>
|
||
// 加载统计
|
||
function loadStats() {
|
||
fetch('/api/stats')
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
document.getElementById('stat-requests').textContent = data.total_requests || 0;
|
||
document.getElementById('stat-tasks').textContent = data.total_tasks || 0;
|
||
document.getElementById('stat-agents').textContent = data.total_agents || 0;
|
||
document.getElementById('stat-active').textContent = data.active_executions || 0;
|
||
});
|
||
}
|
||
|
||
// 日志输出
|
||
function log(text, type = 'info') {
|
||
const logArea = document.getElementById('log-output');
|
||
const time = new Date().toLocaleTimeString();
|
||
const color = type === 'error' ? '#ff6b6b' : type === 'success' ? '#51cf66' : '#74c0fc';
|
||
logArea.innerHTML += `<span style="color:${color}">[${time}] ${text}</span>\n`;
|
||
logArea.scrollTop = logArea.scrollHeight;
|
||
}
|
||
|
||
// 提交请求
|
||
document.getElementById('submit-btn').addEventListener('click', async () => {
|
||
const input = document.getElementById('user-input').value.trim();
|
||
if (!input) {
|
||
log('请输入请求内容', 'error');
|
||
return;
|
||
}
|
||
|
||
log('发送请求...');
|
||
document.getElementById('submit-btn').disabled = true;
|
||
|
||
try {
|
||
const response = await fetch('/api/request', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({content: input})
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.error) {
|
||
log(`错误: ${data.error}`, 'error');
|
||
} else {
|
||
log(`请求ID: ${data.id}`, 'success');
|
||
log(`状态: ${data.status}`);
|
||
|
||
if (data.task_graph) {
|
||
const tasks = Object.keys(data.task_graph.tasks);
|
||
log(`拆分任务: ${tasks.length} 个`);
|
||
}
|
||
|
||
if (data.final_result) {
|
||
log(`结果: ${JSON.stringify(data.final_result)}`, 'success');
|
||
}
|
||
}
|
||
|
||
} catch (e) {
|
||
log(`请求失败: ${e}`, 'error');
|
||
}
|
||
|
||
document.getElementById('submit-btn').disabled = false;
|
||
loadStats();
|
||
});
|
||
|
||
// 快速测试
|
||
async function quickTest(type) {
|
||
const input = document.getElementById('user-input').value.trim() || '帮我写一个Python爬虫';
|
||
log(`测试 ${type}...`);
|
||
|
||
try {
|
||
const url = type === 'intent' ? '/api/test_intent' :
|
||
type === 'split' ? '/api/test_split' : '/api/request';
|
||
|
||
const response = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify(type === 'full' ? {content: input} : {prompt: input})
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.error) {
|
||
log(`错误: ${data.error}`, 'error');
|
||
} else {
|
||
log(`结果:`, 'success');
|
||
log(JSON.stringify(data.intent || data.tasks || data, null, 2));
|
||
}
|
||
|
||
} catch (e) {
|
||
log(`测试失败: ${e}`, 'error');
|
||
}
|
||
|
||
loadStats();
|
||
}
|
||
|
||
// 初始化
|
||
loadStats();
|
||
</script>
|
||
</body>
|
||
</html> |