commit
76e00284d0
@ -178,7 +178,7 @@ async def _query_model_usage_rows(sor, conditions, limit=None, offset=None):
|
||||
sql = """
|
||||
SELECT id, userid, llmid, original_price, orderid, bill_status, usage_content, created_at
|
||||
FROM model_usage
|
||||
WHERE %s
|
||||
WHERE %s AND bill_status != '0'
|
||||
ORDER BY created_at DESC
|
||||
""" % where_clause
|
||||
if limit is not None:
|
||||
@ -188,7 +188,7 @@ async def _query_model_usage_rows(sor, conditions, limit=None, offset=None):
|
||||
|
||||
async def _count_model_usage(sor, conditions):
|
||||
where_clause = ' AND '.join(conditions) if conditions else '1 = 1'
|
||||
sql = 'SELECT COUNT(*) AS total_count FROM model_usage WHERE %s' % where_clause
|
||||
sql = 'SELECT COUNT(*) AS total_count FROM model_usage WHERE %s AND bill_status != "0"' % where_clause
|
||||
return (await sor.sqlExe(sql, {}))[0]['total_count']
|
||||
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ def _normalize_usage_row(row, bill_amount_map=None):
|
||||
'prompt_tokens': int(usage.get('prompt_tokens') or 0),
|
||||
'completion_tokens': int(usage.get('completion_tokens') or 0),
|
||||
'total_tokens': int(usage.get('total_tokens') or 0),
|
||||
'amount': round(amount, 4),
|
||||
'amount': round(amount, 2),
|
||||
'bill_status': row.get('bill_status'),
|
||||
'orderid': orderid,
|
||||
'usage_time': row.get('created_at'),
|
||||
@ -155,7 +155,7 @@ async def _query_model_usage_rows(sor, conditions, limit=None, offset=None):
|
||||
sql = """
|
||||
SELECT id, userid, llmid, original_price, orderid, bill_status, usage_content, created_at
|
||||
FROM model_usage
|
||||
WHERE %s
|
||||
WHERE %s AND bill_status != '0'
|
||||
ORDER BY created_at DESC
|
||||
""" % where_clause
|
||||
if limit is not None:
|
||||
@ -165,7 +165,7 @@ async def _query_model_usage_rows(sor, conditions, limit=None, offset=None):
|
||||
|
||||
async def _count_model_usage(sor, conditions):
|
||||
where_clause = ' AND '.join(conditions) if conditions else '1 = 1'
|
||||
sql = 'SELECT COUNT(*) AS total_count FROM model_usage WHERE %s' % where_clause
|
||||
sql = 'SELECT COUNT(*) AS total_count FROM model_usage WHERE %s AND bill_status != "0"' % where_clause
|
||||
return (await sor.sqlExe(sql, {}))[0]['total_count']
|
||||
|
||||
|
||||
|
||||
@ -260,6 +260,13 @@ async def process_user_billing(ns={}):
|
||||
'status': 'error',
|
||||
'msg': 'llmid必传'
|
||||
}
|
||||
model_name = ns.get('model')
|
||||
if not model_name:
|
||||
debug(f"{userid} process_user_billing model必传")
|
||||
return {
|
||||
'status': 'error',
|
||||
'msg': 'model必传'
|
||||
}
|
||||
|
||||
try:
|
||||
amount = round(float(amount), 12)
|
||||
@ -275,6 +282,9 @@ async def process_user_billing(ns={}):
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
product_li = await sor.R('product', {'providerpid': llmid, 'del_flg': '0'})
|
||||
if not product_li:
|
||||
product_li = await sor.R('product', {'product_code': model_name, 'del_flg': '0'})
|
||||
|
||||
if not product_li:
|
||||
debug(f"{userid} process_user_billing 未找到对应产品,请确认")
|
||||
return {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<span class="title-icon">
|
||||
<i class="el-icon-data-line"></i>
|
||||
</span>
|
||||
<h2>Token用量</h2>
|
||||
<h2>Token用量</h2>
|
||||
</div>
|
||||
<p>查看模型调用 Token 消耗、调用次数和费用趋势。</p>
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
|
||||
|
||||
<div class="stat-row">
|
||||
<div v-for="item in statCards" :key="item.label" class="stat-card" :class="item.type">
|
||||
<div class="stat-card-head">
|
||||
@ -71,7 +71,7 @@
|
||||
></el-input>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
type="daterange"
|
||||
size="small"
|
||||
value-format="yyyy-MM-dd"
|
||||
range-separator="至"
|
||||
@ -296,6 +296,8 @@ export default {
|
||||
formatter: '{b}: {c} Token ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
bottom: 0,
|
||||
icon: 'circle',
|
||||
textStyle: {
|
||||
@ -307,11 +309,20 @@ export default {
|
||||
{
|
||||
name: 'Token占比',
|
||||
type: 'pie',
|
||||
radius: ['52%', '72%'],
|
||||
center: ['50%', '44%'],
|
||||
radius: ['55%', '70%'],
|
||||
center: ['50%', '48%'],
|
||||
avoidLabelOverlap: true,
|
||||
label: {
|
||||
formatter: '{b}\n{d}%'
|
||||
show: true,
|
||||
position: 'outside',
|
||||
formatter: '{b}\n{d}%',
|
||||
lineHeight: 18,
|
||||
fontSize: 12
|
||||
},
|
||||
labelLine: {
|
||||
length: 8,
|
||||
length2: 12,
|
||||
smooth: true
|
||||
},
|
||||
data: hasData
|
||||
? [
|
||||
@ -321,7 +332,7 @@ export default {
|
||||
: [{ name: '暂无数据', value: 1 }],
|
||||
itemStyle: {
|
||||
borderColor: '#fff',
|
||||
borderWidth: 3
|
||||
borderWidth: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -332,10 +343,11 @@ export default {
|
||||
const rankList = this.modelUsageRank.slice().reverse()
|
||||
this.modelRankChart.setOption({
|
||||
grid: {
|
||||
top: 12,
|
||||
right: 24,
|
||||
bottom: 20,
|
||||
left: 92
|
||||
top: 24,
|
||||
right: 30,
|
||||
bottom: 28,
|
||||
left: 100,
|
||||
containLabel: false
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
@ -371,15 +383,16 @@ export default {
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
color: '#606266',
|
||||
width: 82,
|
||||
overflow: 'truncate'
|
||||
width: 88,
|
||||
overflow: 'truncate',
|
||||
margin: 8
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Token消耗',
|
||||
type: 'bar',
|
||||
barWidth: 12,
|
||||
barWidth: 14,
|
||||
data: rankList.map(item => item.total_tokens),
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
@ -392,6 +405,7 @@ export default {
|
||||
show: true,
|
||||
position: 'right',
|
||||
color: '#344054',
|
||||
fontSize: 11,
|
||||
formatter: params => this.formatNumber(params.value)
|
||||
}
|
||||
}
|
||||
@ -657,11 +671,11 @@ export default {
|
||||
|
||||
.chart-box {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
height: 260px;
|
||||
}
|
||||
|
||||
.model-rank-chart {
|
||||
height: 300px;
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
.ratio-list,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user