refactor(config): 移除废弃的数据库配置模块
旧的数据库配置模块 `src/common/database/config` 已被完全移除。该模块已被标记为废弃,其功能已统一整合到 `global_config` 中。 本次重构旨在: - 简化代码库,消除冗余和过时的文件。 - 统一配置管理,提高可维护性。 此外,对 `AttentionOptimizer` 中的类变量添加了 `ClassVar` 类型注解,以增强代码的清晰度和类型安全性。
This commit is contained in:
833
mofox_bot_statistics.html
Normal file
833
mofox_bot_statistics.html
Normal file
@@ -0,0 +1,833 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MoFox-Bot运行统计报告</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>/* General Body Styles */
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #F8F9FA; /* Light grey background */
|
||||
color: #495057; /* Softer text color */
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Main Container */
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 20px auto;
|
||||
background-color: #FFFFFF; /* Pure white background */
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
|
||||
border: 1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
/* Dashboard Layout */
|
||||
.dashboard-layout {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 65%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
flex: 35%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Responsive Design for Mobile */
|
||||
@media (max-width: 992px) {
|
||||
.dashboard-layout {
|
||||
flex-direction: column;
|
||||
}
|
||||
.main-content, .sidebar-content {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
h1, h2 {
|
||||
color: #212529;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 2.2em;
|
||||
margin-bottom: 20px;
|
||||
color: #4A90E2; /* Main blue for title */
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 2px solid #EAEAEA;
|
||||
}
|
||||
|
||||
/* Info Banners */
|
||||
.info-item {
|
||||
background-color: #E9ECEF;
|
||||
padding: 10px 15px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.95em;
|
||||
border: 1px solid #DEE2E6;
|
||||
}
|
||||
|
||||
.info-item strong {
|
||||
color: #4A90E2;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.tabs {
|
||||
border-bottom: 2px solid #DEE2E6;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tabs button {
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 14px 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 16px;
|
||||
color: #6C757D;
|
||||
border-bottom: 3px solid transparent;
|
||||
margin-bottom: -2px; /* Align with container border */
|
||||
}
|
||||
|
||||
.tabs button:hover {
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.tabs button.active {
|
||||
color: #4A90E2;
|
||||
border-bottom-color: #4A90E2;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Summary Cards */
|
||||
.summary-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #FFFFFF;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
border: 1px solid #EAEAEA;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 15px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 1em;
|
||||
color: #6C757D;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.8em;
|
||||
font-weight: bold;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 15px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #4A90E2;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 0.95em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #F8F9FA;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background-color: #E9ECEF;
|
||||
}
|
||||
|
||||
/* Chart Container in Sidebar */
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height: 300px; /* Adjust height as needed */
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
font-size: 0.85em;
|
||||
color: #6C757D;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>MoFox-Bot运行统计报告</h1>
|
||||
<p class="info-item"><strong>统计截止时间:</strong> 2025-11-13 12:50:57</p>
|
||||
<div class="tabs"><button class="tab-link" onclick="showTab(event, 'last_7_days')">最近7天</button>
|
||||
<button class="tab-link" onclick="showTab(event, 'last_24_hours')">最近24小时</button>
|
||||
<button class="tab-link" onclick="showTab(event, 'last_3_hours')">最近3小时</button>
|
||||
<button class="tab-link" onclick="showTab(event, 'last_hour')">最近1小时</button>
|
||||
<button class="tab-link" onclick="showTab(event, 'all_time')">自部署以来的</button>
|
||||
<button class="tab-link" onclick="showTab(event, 'charts')">数据图表</button></div>
|
||||
<div id="last_7_days" class="tab-content">
|
||||
<div class="dashboard-layout">
|
||||
<div class="main-content">
|
||||
<p class="info-item">
|
||||
<strong>统计时段: </strong>
|
||||
2025-11-06 12:50:57 ~ 2025-11-13 12:50:57
|
||||
</p>
|
||||
|
||||
<div class="summary-cards">
|
||||
<div class="card">
|
||||
<h3>总花费</h3>
|
||||
<p>0.0000 ¥</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总请求数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总Token数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总消息数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总在线时间</h3>
|
||||
<p>4小时31分钟40秒</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>按模型分类统计</h2>
|
||||
<table>
|
||||
<tr><th>模型名称</th><th>调用次数</th><th>平均Token数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th><th>平均耗时(秒)</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按供应商分类统计</h2>
|
||||
<table>
|
||||
<tr><th>供应商名称</th><th>调用次数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按模块分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>模块名称</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按请求类型分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>请求类型</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>聊天消息统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>联系人/群组名称</th><th>消息数量</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<h2>数据总览</h2>
|
||||
<div class="chart-grid">
|
||||
<div class="chart-container">
|
||||
<canvas id="providerCostPieChart_last_7_days"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="modelCostBarChart_last_7_days"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="last_24_hours" class="tab-content">
|
||||
<div class="dashboard-layout">
|
||||
<div class="main-content">
|
||||
<p class="info-item">
|
||||
<strong>统计时段: </strong>
|
||||
2025-11-12 12:50:57 ~ 2025-11-13 12:50:57
|
||||
</p>
|
||||
|
||||
<div class="summary-cards">
|
||||
<div class="card">
|
||||
<h3>总花费</h3>
|
||||
<p>0.0000 ¥</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总请求数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总Token数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总消息数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总在线时间</h3>
|
||||
<p>30分钟8秒</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>按模型分类统计</h2>
|
||||
<table>
|
||||
<tr><th>模型名称</th><th>调用次数</th><th>平均Token数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th><th>平均耗时(秒)</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按供应商分类统计</h2>
|
||||
<table>
|
||||
<tr><th>供应商名称</th><th>调用次数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按模块分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>模块名称</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按请求类型分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>请求类型</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>聊天消息统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>联系人/群组名称</th><th>消息数量</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<h2>数据总览</h2>
|
||||
<div class="chart-grid">
|
||||
<div class="chart-container">
|
||||
<canvas id="providerCostPieChart_last_24_hours"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="modelCostBarChart_last_24_hours"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="last_3_hours" class="tab-content">
|
||||
<div class="dashboard-layout">
|
||||
<div class="main-content">
|
||||
<p class="info-item">
|
||||
<strong>统计时段: </strong>
|
||||
2025-11-13 09:50:57 ~ 2025-11-13 12:50:57
|
||||
</p>
|
||||
|
||||
<div class="summary-cards">
|
||||
<div class="card">
|
||||
<h3>总花费</h3>
|
||||
<p>0.0000 ¥</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总请求数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总Token数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总消息数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总在线时间</h3>
|
||||
<p>17分钟39秒</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>按模型分类统计</h2>
|
||||
<table>
|
||||
<tr><th>模型名称</th><th>调用次数</th><th>平均Token数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th><th>平均耗时(秒)</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按供应商分类统计</h2>
|
||||
<table>
|
||||
<tr><th>供应商名称</th><th>调用次数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按模块分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>模块名称</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按请求类型分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>请求类型</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>聊天消息统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>联系人/群组名称</th><th>消息数量</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<h2>数据总览</h2>
|
||||
<div class="chart-grid">
|
||||
<div class="chart-container">
|
||||
<canvas id="providerCostPieChart_last_3_hours"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="modelCostBarChart_last_3_hours"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="last_hour" class="tab-content">
|
||||
<div class="dashboard-layout">
|
||||
<div class="main-content">
|
||||
<p class="info-item">
|
||||
<strong>统计时段: </strong>
|
||||
2025-11-13 11:50:57 ~ 2025-11-13 12:50:57
|
||||
</p>
|
||||
|
||||
<div class="summary-cards">
|
||||
<div class="card">
|
||||
<h3>总花费</h3>
|
||||
<p>0.0000 ¥</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总请求数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总Token数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总消息数</h3>
|
||||
<p>0</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总在线时间</h3>
|
||||
<p>13分钟56秒</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>按模型分类统计</h2>
|
||||
<table>
|
||||
<tr><th>模型名称</th><th>调用次数</th><th>平均Token数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th><th>平均耗时(秒)</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按供应商分类统计</h2>
|
||||
<table>
|
||||
<tr><th>供应商名称</th><th>调用次数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按模块分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>模块名称</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按请求类型分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>请求类型</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>聊天消息统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>联系人/群组名称</th><th>消息数量</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<h2>数据总览</h2>
|
||||
<div class="chart-grid">
|
||||
<div class="chart-container">
|
||||
<canvas id="providerCostPieChart_last_hour"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="modelCostBarChart_last_hour"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="all_time" class="tab-content">
|
||||
<div class="dashboard-layout">
|
||||
<div class="main-content">
|
||||
<p class="info-item">
|
||||
<strong>统计时段: </strong>
|
||||
2025-10-02 21:26:50 ~ 2025-11-13 12:50:57
|
||||
</p>
|
||||
|
||||
<div class="summary-cards">
|
||||
<div class="card">
|
||||
<h3>总花费</h3>
|
||||
<p>2234.0000 ¥</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总请求数</h3>
|
||||
<p>2234</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总Token数</h3>
|
||||
<p>1218356</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总消息数</h3>
|
||||
<p>994</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>总在线时间</h3>
|
||||
<p>4小时57分钟30秒</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>按模型分类统计</h2>
|
||||
<table>
|
||||
<tr><th>模型名称</th><th>调用次数</th><th>平均Token数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th><th>平均耗时(秒)</th></tr>
|
||||
<tbody><tr><td>BAAI/bge-m3</td><td>1121</td><td>0</td><td>48256</td><td>0.00</td><td>0.0000 ¥</td><td>1121.0000 ¥</td><td>78.608 秒</td></tr>
|
||||
<tr><td>Qwen/Qwen2.5-VL-72B-Instruct</td><td>50</td><td>0</td><td>66700</td><td>0.00</td><td>0.0000 ¥</td><td>50.0000 ¥</td><td>366.725 秒</td></tr>
|
||||
<tr><td>Qwen/Qwen3-14B</td><td>70</td><td>0</td><td>90191</td><td>0.00</td><td>0.0000 ¥</td><td>70.0000 ¥</td><td>31.441 秒</td></tr>
|
||||
<tr><td>Qwen/Qwen3-30B-A3B</td><td>453</td><td>0</td><td>281944</td><td>0.00</td><td>0.0000 ¥</td><td>453.0000 ¥</td><td>75.589 秒</td></tr>
|
||||
<tr><td>Qwen/Qwen3-8B</td><td>9</td><td>0</td><td>6682</td><td>0.00</td><td>0.0000 ¥</td><td>9.0000 ¥</td><td>8.275 秒</td></tr>
|
||||
<tr><td>deepseek-ai/DeepSeek-R1-Distill-Qwen-32B</td><td>21</td><td>0</td><td>11811</td><td>0.00</td><td>0.0000 ¥</td><td>21.0000 ¥</td><td>11.524 秒</td></tr>
|
||||
<tr><td>deepseek-ai/DeepSeek-V3.1-Terminus</td><td>428</td><td>0</td><td>623224</td><td>0.00</td><td>0.0000 ¥</td><td>428.0000 ¥</td><td>2324.821 秒</td></tr>
|
||||
<tr><td>deepseek-ai/DeepSeek-V3.2-Exp</td><td>3</td><td>0</td><td>4267</td><td>0.00</td><td>0.0000 ¥</td><td>3.0000 ¥</td><td>80.927 秒</td></tr>
|
||||
<tr><td>gemini-2.5-pro</td><td>69</td><td>0</td><td>68195</td><td>0.00</td><td>0.0000 ¥</td><td>69.0000 ¥</td><td>898.429 秒</td></tr>
|
||||
<tr><td>moonshotai/Kimi-K2-Instruct</td><td>10</td><td>0</td><td>17086</td><td>0.00</td><td>0.0000 ¥</td><td>10.0000 ¥</td><td>35.644 秒</td></tr></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按供应商分类统计</h2>
|
||||
<table>
|
||||
<tr><th>供应商名称</th><th>调用次数</th><th>Token总量</th><th>TPS</th><th>每K Token成本</th><th>累计花费</th></tr>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按模块分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>模块名称</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody><tr><td>action</td><td>372</td><td>210218</td><td>372</td><td>210590</td><td>372.0000 ¥</td><td>61.562 秒</td><td>28.224 秒</td></tr>
|
||||
<tr><td>chat</td><td>16</td><td>32338</td><td>149</td><td>32487</td><td>16.0000 ¥</td><td>347.109 秒</td><td>1.013 秒</td></tr>
|
||||
<tr><td>chat_stream_impression_update</td><td>4</td><td>2504</td><td>926</td><td>3430</td><td>4.0000 ¥</td><td>38.162 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>embedding</td><td>356</td><td>31947</td><td>0</td><td>31947</td><td>356.0000 ¥</td><td>71.454 秒</td><td>12.687 秒</td></tr>
|
||||
<tr><td>emoji</td><td>23</td><td>8057</td><td>744</td><td>8801</td><td>23.0000 ¥</td><td>248.367 秒</td><td>3.224 秒</td></tr>
|
||||
<tr><td>expressor</td><td>57</td><td>46135</td><td>168</td><td>46303</td><td>57.0000 ¥</td><td>453.845 秒</td><td>282.887 秒</td></tr>
|
||||
<tr><td>image</td><td>41</td><td>52607</td><td>6169</td><td>58776</td><td>41.0000 ¥</td><td>268.468 秒</td><td>31.588 秒</td></tr>
|
||||
<tr><td>individuality</td><td>1</td><td>140</td><td>23</td><td>163</td><td>1.0000 ¥</td><td>1.808 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>interest_embedding</td><td>765</td><td>16309</td><td>0</td><td>16309</td><td>765.0000 ¥</td><td>30.717 秒</td><td>6.880 秒</td></tr>
|
||||
<tr><td>interest_generation</td><td>2</td><td>965</td><td>316</td><td>1281</td><td>2.0000 ¥</td><td>50.171 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>memory</td><td>139</td><td>177182</td><td>31665</td><td>208847</td><td>139.0000 ¥</td><td>1306.658 秒</td><td>45.801 秒</td></tr>
|
||||
<tr><td>monthly_plan</td><td>2</td><td>740</td><td>353</td><td>1093</td><td>2.0000 ¥</td><td>10.196 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>mood</td><td>126</td><td>40413</td><td>1621</td><td>42034</td><td>126.0000 ¥</td><td>585.337 秒</td><td>298.293 秒</td></tr>
|
||||
<tr><td>planner</td><td>61</td><td>157672</td><td>10085</td><td>167757</td><td>61.0000 ¥</td><td>310.203 秒</td><td>18.367 秒</td></tr>
|
||||
<tr><td>plugin</td><td>156</td><td>248583</td><td>12858</td><td>261441</td><td>156.0000 ¥</td><td>576.318 秒</td><td>112.317 秒</td></tr>
|
||||
<tr><td>relationship_tracker</td><td>1</td><td>995</td><td>232</td><td>1227</td><td>1.0000 ¥</td><td>17.689 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>schedule</td><td>15</td><td>8360</td><td>9461</td><td>17821</td><td>15.0000 ¥</td><td>388.476 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>tool_executor</td><td>70</td><td>88858</td><td>1333</td><td>90191</td><td>70.0000 ¥</td><td>31.441 秒</td><td>4.774 秒</td></tr>
|
||||
<tr><td>unknown</td><td>21</td><td>4435</td><td>7376</td><td>11811</td><td>21.0000 ¥</td><td>11.524 秒</td><td>3.068 秒</td></tr>
|
||||
<tr><td>video_analysis</td><td>6</td><td>3306</td><td>2741</td><td>6047</td><td>6.0000 ¥</td><td>18.737 秒</td><td>3.772 秒</td></tr></tbody>
|
||||
</table>
|
||||
|
||||
<h2>按请求类型分类统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>请求类型</th><th>调用次数</th><th>输入Token</th><th>输出Token</th><th>Token总量</th><th>累计花费</th><th>平均耗时(秒)</th><th>标准差(秒)</th></tr>
|
||||
</thead>
|
||||
<tbody><tr><td>action.judge</td><td>372</td><td>210218</td><td>372</td><td>210590</td><td>372.0000 ¥</td><td>61.562 秒</td><td>28.224 秒</td></tr>
|
||||
<tr><td>chat.replyer</td><td>16</td><td>32338</td><td>149</td><td>32487</td><td>16.0000 ¥</td><td>347.109 秒</td><td>1.013 秒</td></tr>
|
||||
<tr><td>chat_stream_impression_update</td><td>4</td><td>2504</td><td>926</td><td>3430</td><td>4.0000 ¥</td><td>38.162 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>embedding</td><td>356</td><td>31947</td><td>0</td><td>31947</td><td>356.0000 ¥</td><td>71.454 秒</td><td>12.687 秒</td></tr>
|
||||
<tr><td>emoji</td><td>23</td><td>8057</td><td>744</td><td>8801</td><td>23.0000 ¥</td><td>248.367 秒</td><td>3.224 秒</td></tr>
|
||||
<tr><td>expressor.learner</td><td>57</td><td>46135</td><td>168</td><td>46303</td><td>57.0000 ¥</td><td>453.845 秒</td><td>282.887 秒</td></tr>
|
||||
<tr><td>image</td><td>41</td><td>52607</td><td>6169</td><td>58776</td><td>41.0000 ¥</td><td>268.468 秒</td><td>31.588 秒</td></tr>
|
||||
<tr><td>individuality.compress</td><td>1</td><td>140</td><td>23</td><td>163</td><td>1.0000 ¥</td><td>1.808 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>interest_embedding</td><td>765</td><td>16309</td><td>0</td><td>16309</td><td>765.0000 ¥</td><td>30.717 秒</td><td>6.880 秒</td></tr>
|
||||
<tr><td>interest_generation</td><td>2</td><td>965</td><td>316</td><td>1281</td><td>2.0000 ¥</td><td>50.171 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>memory.extraction</td><td>55</td><td>115032</td><td>22684</td><td>137716</td><td>55.0000 ¥</td><td>1287.156 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>memory.query_planner</td><td>72</td><td>47645</td><td>7262</td><td>54907</td><td>72.0000 ¥</td><td>75.871 秒</td><td>13.881 秒</td></tr>
|
||||
<tr><td>memory.value_assessment</td><td>12</td><td>14505</td><td>1719</td><td>16224</td><td>12.0000 ¥</td><td>43.272 秒</td><td>0.136 秒</td></tr>
|
||||
<tr><td>monthly_plan</td><td>2</td><td>740</td><td>353</td><td>1093</td><td>2.0000 ¥</td><td>10.196 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>mood</td><td>126</td><td>40413</td><td>1621</td><td>42034</td><td>126.0000 ¥</td><td>585.337 秒</td><td>298.293 秒</td></tr>
|
||||
<tr><td>planner</td><td>61</td><td>157672</td><td>10085</td><td>167757</td><td>61.0000 ¥</td><td>310.203 秒</td><td>18.367 秒</td></tr>
|
||||
<tr><td>plugin.generate</td><td>150</td><td>241689</td><td>12847</td><td>254536</td><td>150.0000 ¥</td><td>572.632 秒</td><td>112.215 秒</td></tr>
|
||||
<tr><td>plugin.set_emoji_like.select_emoji</td><td>6</td><td>6894</td><td>11</td><td>6905</td><td>6.0000 ¥</td><td>3.686 秒</td><td>0.102 秒</td></tr>
|
||||
<tr><td>relationship_tracker</td><td>1</td><td>995</td><td>232</td><td>1227</td><td>1.0000 ¥</td><td>17.689 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>schedule</td><td>15</td><td>8360</td><td>9461</td><td>17821</td><td>15.0000 ¥</td><td>388.476 秒</td><td>0.000 秒</td></tr>
|
||||
<tr><td>tool_executor</td><td>70</td><td>88858</td><td>1333</td><td>90191</td><td>70.0000 ¥</td><td>31.441 秒</td><td>4.774 秒</td></tr>
|
||||
<tr><td>unknown</td><td>21</td><td>4435</td><td>7376</td><td>11811</td><td>21.0000 ¥</td><td>11.524 秒</td><td>3.068 秒</td></tr>
|
||||
<tr><td>video_analysis</td><td>6</td><td>3306</td><td>2741</td><td>6047</td><td>6.0000 ¥</td><td>18.737 秒</td><td>3.772 秒</td></tr></tbody>
|
||||
</table>
|
||||
|
||||
<h2>聊天消息统计</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>联系人/群组名称</th><th>消息数量</th></tr>
|
||||
</thead>
|
||||
<tbody><tr><td>MaiCore答疑群(尊王攘夷)</td><td>50</td></tr>
|
||||
<tr><td>因为没有群了所以只能拿这个测试了</td><td>331</td></tr>
|
||||
<tr><td>墨狐狐🌟起源之地</td><td>590</td></tr>
|
||||
<tr><td>亚马逊雨林,一处任何人也找不到的角落(</td><td>4</td></tr>
|
||||
<tr><td>墨狐</td><td>5</td></tr>
|
||||
<tr><td>一闪</td><td>14</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<h2>数据总览</h2>
|
||||
<div class="chart-grid">
|
||||
<div class="chart-container">
|
||||
<canvas id="providerCostPieChart_all_time"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="modelCostBarChart_all_time"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="charts" class="tab-content">
|
||||
<h2>数据图表</h2>
|
||||
<div style="margin: 20px 0; text-align: center;">
|
||||
<label style="margin-right: 10px; font-weight: bold;">时间范围:</label>
|
||||
<button class="time-range-btn" onclick="switchTimeRange('6h')">6小时</button>
|
||||
<button class="time-range-btn" onclick="switchTimeRange('12h')">12小时</button>
|
||||
<button class="time-range-btn" onclick="switchTimeRange('24h')">24小时</button>
|
||||
<button class="time-range-btn" onclick="switchTimeRange('48h')">48小时</button>
|
||||
</div>
|
||||
<div style="margin-top: 20px;">
|
||||
<div style="margin-bottom: 40px;"><canvas id="totalCostChart" width="800" height="400"></canvas></div>
|
||||
<div style="margin-bottom: 40px;"><canvas id="costByModuleChart" width="800" height="400"></canvas></div>
|
||||
<div style="margin-bottom: 40px;"><canvas id="costByModelChart" width="800" height="400"></canvas></div>
|
||||
<div><canvas id="messageByChatChart" width="800" height="400"></canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>let i, tab_content, tab_links;
|
||||
tab_content = document.getElementsByClassName("tab-content");
|
||||
tab_links = document.getElementsByClassName("tab-link");
|
||||
if (tab_content.length > 0) tab_content[0].classList.add("active");
|
||||
if (tab_links.length > 0) tab_links[0].classList.add("active");
|
||||
function showTab(evt, tabName) {
|
||||
for (i = 0; i < tab_content.length; i++) tab_content[i].classList.remove("active");
|
||||
for (i = 0; i < tab_links.length; i++) tab_links[i].classList.remove("active");
|
||||
document.getElementById(tabName).classList.add("active");
|
||||
evt.currentTarget.classList.add("active");
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// This is a placeholder for chart data which will be injected by python.
|
||||
const allChartData = JSON.parse('{{ all_chart_data }}')
|
||||
;
|
||||
let currentCharts = {};
|
||||
const chartConfigs = {
|
||||
totalCost: { id: 'totalCostChart', title: '总花费', yAxisLabel: '花费 (¥)', dataKey: 'total_cost_data', fill: true },
|
||||
costByModule: { id: 'costByModuleChart', title: '各模块花费', yAxisLabel: '花费 (¥)', dataKey: 'cost_by_module', fill: false },
|
||||
costByModel: { id: 'costByModelChart', title: '各模型花费', yAxisLabel: '花费 (¥)', dataKey: 'cost_by_model', fill: false },
|
||||
messageByChat: { id: 'messageByChatChart', title: '各聊天流消息数', yAxisLabel: '消息数', dataKey: 'message_by_chat', fill: false }
|
||||
};
|
||||
|
||||
window.switchTimeRange = function(timeRange) {
|
||||
document.querySelectorAll('.time-range-btn').forEach(btn => btn.classList.remove('active'));
|
||||
event.target.classList.add('active');
|
||||
updateAllCharts(allChartData[timeRange], timeRange);
|
||||
}
|
||||
|
||||
function updateAllCharts(data, timeRange) {
|
||||
Object.values(currentCharts).forEach(chart => chart && chart.destroy());
|
||||
currentCharts = {};
|
||||
Object.keys(chartConfigs).forEach(type => createChart(type, data, timeRange));
|
||||
}
|
||||
|
||||
function createChart(chartType, data, timeRange) {
|
||||
const config = chartConfigs[chartType];
|
||||
if (!data || !data[config.dataKey]) return;
|
||||
const colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#34495e', '#e67e22', '#95a5a6', '#f1c40f'];
|
||||
let datasets = [];
|
||||
if (chartType === 'totalCost') {
|
||||
datasets = [{ label: config.title, data: data[config.dataKey], borderColor: colors[0], backgroundColor: 'rgba(52, 152, 219, 0.1)', tension: 0.4, fill: config.fill }];
|
||||
} else {
|
||||
let i = 0;
|
||||
Object.entries(data[config.dataKey]).forEach(([name, chartData]) => {
|
||||
datasets.push({ label: name, data: chartData, borderColor: colors[i % colors.length], backgroundColor: colors[i % colors.length] + '20', tension: 0.4, fill: config.fill });
|
||||
i++;
|
||||
});
|
||||
}
|
||||
currentCharts[chartType] = new Chart(document.getElementById(config.id), {
|
||||
type: 'line',
|
||||
data: { labels: data.time_labels, datasets: datasets },
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: { title: { display: true, text: `${timeRange}内${config.title}趋势`, font: { size: 16 } }, legend: { display: chartType !== 'totalCost', position: 'top' } },
|
||||
scales: { x: { title: { display: true, text: '时间' }, ticks: { maxTicksLimit: 12 } }, y: { title: { display: true, text: config.yAxisLabel }, beginAtZero: true } },
|
||||
interaction: { intersect: false, mode: 'index' }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (allChartData['24h']) {
|
||||
updateAllCharts(allChartData['24h'], '24h');
|
||||
// Activate the 24h button by default
|
||||
document.querySelectorAll('.time-range-btn').forEach(btn => {
|
||||
if (btn.textContent.includes('24小时')) {
|
||||
btn.classList.add('active');
|
||||
} else {
|
||||
btn.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Static charts
|
||||
const staticChartData = JSON.parse('{{ static_chart_data }}')
|
||||
;
|
||||
Object.keys(staticChartData).forEach(period_id => {
|
||||
const providerCostData = staticChartData[period_id].provider_cost_data;
|
||||
const modelCostData = staticChartData[period_id].model_cost_data;
|
||||
const colors = ['#3498db', '#2ecc71', '#f1c40f', '#e74c3c', '#9b59b6', '#1abc9c', '#34495e', '#e67e22'];
|
||||
|
||||
// Provider Cost Pie Chart
|
||||
const providerCtx = document.getElementById(`providerCostPieChart_${period_id}`);
|
||||
if (providerCtx && providerCostData && providerCostData.data.length > 0) {
|
||||
new Chart(providerCtx, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: providerCostData.labels,
|
||||
datasets: [{
|
||||
label: '按供应商花费',
|
||||
data: providerCostData.data,
|
||||
backgroundColor: colors,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: { display: true, text: '按供应商花费分布', font: { size: 16 } },
|
||||
legend: { position: 'top' }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Model Cost Bar Chart
|
||||
const modelCtx = document.getElementById(`modelCostBarChart_${period_id}`);
|
||||
if (modelCtx && modelCostData && modelCostData.data.length > 0) {
|
||||
new Chart(modelCtx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: modelCostData.labels,
|
||||
datasets: [{
|
||||
label: '按模型花费',
|
||||
data: modelCostData.data,
|
||||
backgroundColor: colors,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: { display: true, text: '按模型花费排行', font: { size: 16 } },
|
||||
legend: { display: false }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: '花费 (¥)' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,7 +13,7 @@
|
||||
import hashlib
|
||||
import random
|
||||
import re
|
||||
from typing import Any, Literal
|
||||
from typing import Any, ClassVar, Literal
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
@@ -26,7 +26,7 @@ class AttentionOptimizer:
|
||||
|
||||
# 可交换的block组定义(组内block可以随机排序)
|
||||
# 每个组是一个列表,包含可以互换位置的block名称
|
||||
SWAPPABLE_BLOCK_GROUPS = [
|
||||
SWAPPABLE_BLOCK_GROUPS:ClassVar = [
|
||||
# 用户相关信息组(记忆、关系、表达习惯)
|
||||
["memory_block", "relation_info_block", "expression_habits_block"],
|
||||
# 上下文增强组(工具、知识、跨群)
|
||||
@@ -37,7 +37,7 @@ class AttentionOptimizer:
|
||||
|
||||
# 语义等价的文本替换模板
|
||||
# 格式: {原始文本: [替换选项1, 替换选项2, ...]}
|
||||
SEMANTIC_VARIANTS = {
|
||||
SEMANTIC_VARIANTS:ClassVar = {
|
||||
"当前时间": ["当前时间", "现在是", "此时此刻", "时间"],
|
||||
"最近的系统通知": ["最近的系统通知", "系统通知", "通知消息", "最新通知"],
|
||||
"聊天历史": ["聊天历史", "对话记录", "历史消息", "之前的对话"],
|
||||
@@ -125,7 +125,7 @@ class AttentionOptimizer:
|
||||
for group in self.SWAPPABLE_BLOCK_GROUPS:
|
||||
# 过滤出实际存在且非空的block
|
||||
existing_blocks = [
|
||||
block for block in group if block in context_data and context_data[block]
|
||||
block for block in group if context_data.get(block)
|
||||
]
|
||||
|
||||
if len(existing_blocks) > 1:
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
"""数据库配置层
|
||||
|
||||
职责:
|
||||
- 数据库配置现已集成到全局配置中
|
||||
- 通过 src.config.config.global_config.database 访问
|
||||
- 优化参数配置
|
||||
|
||||
注意:此模块已废弃,配置已迁移到 global_config
|
||||
"""
|
||||
|
||||
__all__ = []
|
||||
@@ -1,149 +0,0 @@
|
||||
"""数据库配置管理
|
||||
|
||||
统一管理数据库连接配置
|
||||
"""
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("database_config")
|
||||
|
||||
|
||||
@dataclass
|
||||
class DatabaseConfig:
|
||||
"""数据库配置"""
|
||||
|
||||
# 基础配置
|
||||
db_type: str # "sqlite" 或 "mysql"
|
||||
url: str # 数据库连接URL
|
||||
|
||||
# 引擎配置
|
||||
engine_kwargs: dict[str, Any]
|
||||
|
||||
# SQLite特定配置
|
||||
sqlite_path: str | None = None
|
||||
|
||||
# MySQL特定配置
|
||||
mysql_host: str | None = None
|
||||
mysql_port: int | None = None
|
||||
mysql_user: str | None = None
|
||||
mysql_password: str | None = None
|
||||
mysql_database: str | None = None
|
||||
mysql_charset: str = "utf8mb4"
|
||||
mysql_unix_socket: str | None = None
|
||||
|
||||
|
||||
_database_config: DatabaseConfig | None = None
|
||||
|
||||
|
||||
def get_database_config() -> DatabaseConfig:
|
||||
"""获取数据库配置
|
||||
|
||||
从全局配置中读取数据库设置并构建配置对象
|
||||
"""
|
||||
global _database_config
|
||||
|
||||
if _database_config is not None:
|
||||
return _database_config
|
||||
|
||||
from src.config.config import global_config
|
||||
|
||||
config = global_config.database
|
||||
|
||||
# 构建数据库URL
|
||||
if config.database_type == "mysql":
|
||||
# MySQL配置
|
||||
encoded_user = quote_plus(config.mysql_user)
|
||||
encoded_password = quote_plus(config.mysql_password)
|
||||
|
||||
if config.mysql_unix_socket:
|
||||
# Unix socket连接
|
||||
encoded_socket = quote_plus(config.mysql_unix_socket)
|
||||
url = (
|
||||
f"mysql+aiomysql://{encoded_user}:{encoded_password}"
|
||||
f"@/{config.mysql_database}"
|
||||
f"?unix_socket={encoded_socket}&charset={config.mysql_charset}"
|
||||
)
|
||||
else:
|
||||
# TCP连接
|
||||
url = (
|
||||
f"mysql+aiomysql://{encoded_user}:{encoded_password}"
|
||||
f"@{config.mysql_host}:{config.mysql_port}/{config.mysql_database}"
|
||||
f"?charset={config.mysql_charset}"
|
||||
)
|
||||
|
||||
engine_kwargs = {
|
||||
"echo": False,
|
||||
"future": True,
|
||||
"pool_size": config.connection_pool_size,
|
||||
"max_overflow": config.connection_pool_size * 2,
|
||||
"pool_timeout": config.connection_timeout,
|
||||
"pool_recycle": 3600,
|
||||
"pool_pre_ping": True,
|
||||
"connect_args": {
|
||||
"autocommit": config.mysql_autocommit,
|
||||
"charset": config.mysql_charset,
|
||||
"connect_timeout": config.connection_timeout,
|
||||
},
|
||||
}
|
||||
|
||||
_database_config = DatabaseConfig(
|
||||
db_type="mysql",
|
||||
url=url,
|
||||
engine_kwargs=engine_kwargs,
|
||||
mysql_host=config.mysql_host,
|
||||
mysql_port=config.mysql_port,
|
||||
mysql_user=config.mysql_user,
|
||||
mysql_password=config.mysql_password,
|
||||
mysql_database=config.mysql_database,
|
||||
mysql_charset=config.mysql_charset,
|
||||
mysql_unix_socket=config.mysql_unix_socket,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"MySQL配置已加载: "
|
||||
f"{config.mysql_user}@{config.mysql_host}:{config.mysql_port}/{config.mysql_database}"
|
||||
)
|
||||
|
||||
else:
|
||||
# SQLite配置
|
||||
if not os.path.isabs(config.sqlite_path):
|
||||
ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."))
|
||||
db_path = os.path.join(ROOT_PATH, config.sqlite_path)
|
||||
else:
|
||||
db_path = config.sqlite_path
|
||||
|
||||
# 确保数据库目录存在
|
||||
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
||||
|
||||
url = f"sqlite+aiosqlite:///{db_path}"
|
||||
|
||||
engine_kwargs = {
|
||||
"echo": False,
|
||||
"future": True,
|
||||
"connect_args": {
|
||||
"check_same_thread": False,
|
||||
"timeout": 60,
|
||||
},
|
||||
}
|
||||
|
||||
_database_config = DatabaseConfig(
|
||||
db_type="sqlite",
|
||||
url=url,
|
||||
engine_kwargs=engine_kwargs,
|
||||
sqlite_path=db_path,
|
||||
)
|
||||
|
||||
logger.info(f"SQLite配置已加载: {db_path}")
|
||||
|
||||
return _database_config
|
||||
|
||||
|
||||
def reset_database_config():
|
||||
"""重置数据库配置(用于测试)"""
|
||||
global _database_config
|
||||
_database_config = None
|
||||
Reference in New Issue
Block a user