LLM监控系统搭建:API调用统计与性能指标分析
痛点与解决方案
你是否还在为LLM(Large Language Model,大型语言模型)API调用的成本失控而烦恼?是否难以追踪不同模型的性能差异?本文将详细介绍如何利用LLM自带的日志系统和扩展工具,构建完整的API调用监控方案,帮助你实现调用统计、性能分析和成本优化。
读完本文后,你将能够:
- 启用并配置LLM的SQLite日志系统
- 实时监控API调用次数、响应时间和token消耗
- 分析不同模型的性能指标与成本效益
- 设置自动化告警与报告生成
- 优化模型选择与调用策略
系统架构与工作原理
LLM监控系统主要由三个核心组件构成:日志采集层、数据分析层和可视化告警层。
核心组件说明
-
日志采集层:LLM默认将所有API调用记录存储在SQLite数据库中,包含调用时间、模型名称、输入输出token数、响应时长等关键指标。
-
数据分析层:通过LLM提供的命令行工具和自定义SQL查询,对原始日志进行加工处理,计算性能指标和成本数据。
-
可视化告警层:利用Datasette等工具将分析结果可视化,并设置阈值告警,及时发现异常情况。
日志系统配置与启用
日志系统位置与状态查看
LLM默认启用日志功能,所有API调用记录存储在SQLite数据库中。要查看日志数据库位置,执行以下命令:
llm logs path
在Linux系统上,典型路径为:~/.local/share/io.datasette.llm/logs.db
查看日志系统状态:
llm logs status
示例输出:
Logging is ON for all prompts
Found log database at /home/user/.local/share/io.datasette.llm/logs.db
Number of conversations logged: 33
Number of responses logged: 48
Database file size: 19.96MB
日志系统开关控制
启用日志(默认状态):
llm logs on
禁用日志:
llm logs off
临时覆盖默认日志设置:
# 禁用日志时强制记录某次调用
llm "生成月度报告" --log
# 启用日志时不记录某次调用
llm "敏感查询" --no-log
关键指标采集与分析
日志数据结构解析
LLM日志数据库包含多个表,核心指标主要存储在responses表中:
CREATE TABLE "responses" (
[id] TEXT PRIMARY KEY,
[model] TEXT,
[prompt] TEXT,
[system] TEXT,
[prompt_json] TEXT,
[options_json] TEXT,
[response] TEXT,
[response_json] TEXT,
[conversation_id] TEXT REFERENCES [conversations]([id]),
[duration_ms] INTEGER,
[datetime_utc] TEXT,
[input_tokens] INTEGER,
[output_tokens] INTEGER,
[token_details] TEXT,
[schema_id] TEXT REFERENCES [schemas]([id]),
[resolved_model] TEXT
);
核心监控指标说明:
| 指标名称 | 数据类型 | 说明 |
|---|---|---|
model | TEXT | 调用的模型名称 |
duration_ms | INTEGER | 响应时间(毫秒) |
datetime_utc | TEXT | 调用时间(UTC) |
input_tokens | INTEGER | 输入token数量 |
output_tokens | INTEGER | 输出token数量 |
基础统计命令
查看最近10次API调用:
llm logs -n 10
按模型筛选调用记录:
llm logs -m gpt-4o
llm logs -m gemini-1.5-pro
查看特定日期范围的调用:
# 需结合SQLite日期函数使用,详见高级分析部分
高级性能分析与可视化
使用SQL进行深度分析
通过Datasette工具可以直接对日志数据库进行SQL查询和可视化:
# 安装Datasette(如果未安装)
pip install datasette
# 启动Datasette并打开日志数据库
datasette "$(llm logs path)"
在浏览器中访问http://localhost:8001即可进行交互分析。
常用分析SQL示例
- 按模型统计调用次数和平均响应时间:
SELECT
model,
COUNT(*) as call_count,
AVG(duration_ms) as avg_duration_ms,
SUM(input_tokens) as total_input_tokens,
SUM(output_tokens) as total_output_tokens,
SUM(input_tokens + output_tokens) as total_tokens
FROM responses
GROUP BY model
ORDER BY call_count DESC;
- 每日API调用趋势:
SELECT
DATE(datetime_utc) as date,
COUNT(*) as daily_calls,
SUM(input_tokens + output_tokens) as daily_tokens
FROM responses
GROUP BY date
ORDER BY date DESC;
- 响应时间分布分析:
SELECT
model,
COUNT(CASE WHEN duration_ms < 1000 THEN 1 END) as fast_calls,
COUNT(CASE WHEN duration_ms BETWEEN 1000 AND 3000 THEN 1 END) as medium_calls,
COUNT(CASE WHEN duration_ms > 3000 THEN 1 END) as slow_calls
FROM responses
GROUP BY model;
生成性能报告
使用LLM自身能力分析日志并生成报告:
llm logs --json -n 0 | llm -s "分析这些LLM API调用日志,生成性能报告,包括:1.各模型调用次数占比 2.平均响应时间对比 3.token消耗趋势 4.性能优化建议。使用Markdown表格和列表展示结果。"
可视化性能指标
将分析结果导出为CSV,使用Python或Excel创建可视化图表:
# 导出模型性能数据为CSV
datasette "$(llm logs path)" \
--get '/responses.csv?sql=SELECT+model%2C+COUNT%28%2A%29+as+call_count%2C+AVG%28duration_ms%29+as+avg_duration_ms%2C+SUM%28input_tokens+%2B+output_tokens%29+as+total_tokens+FROM+responses+GROUP+BY+model+ORDER+BY+call_count+DESC' \
> model_performance.csv
使用Python Matplotlib生成性能对比图:
import pandas as pd
import matplotlib.pyplot as plt
# 读取CSV数据
df = pd.read_csv('model_performance.csv')
# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
# 创建图表
fig, ax1 = plt.subplots(figsize=(12, 6))
# 绘制调用次数柱状图
bars = ax1.bar(df['model'], df['call_count'], color='skyblue', label='调用次数')
ax1.set_xlabel('模型名称')
ax1.set_ylabel('调用次数', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
plt.xticks(rotation=45, ha='right')
# 创建第二个Y轴显示平均响应时间
ax2 = ax1.twinx()
line = ax2.plot(df['model'], df['avg_duration_ms'], color='red', marker='o', label='平均响应时间(ms)')
ax2.set_ylabel('平均响应时间(ms)', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# 添加图例
plt.legend(bars + line, ['调用次数', '平均响应时间(ms)'], loc='upper right')
plt.title('LLM模型调用统计与性能对比')
plt.tight_layout()
plt.savefig('llm_performance.png', dpi=300)
plt.show()
成本监控与优化
基于token消耗的成本估算
不同模型的token单价差异较大,通过以下SQL可以估算各模型的成本(需根据实际单价调整):
SELECT
model,
COUNT(*) as call_count,
SUM(input_tokens) as input_tokens,
SUM(output_tokens) as output_tokens,
SUM(input_tokens * 0.0015 + output_tokens * 0.006) / 1000 as estimated_cost_usd
FROM responses
WHERE model = 'gpt-4o'
GROUP BY model;
注:以上价格仅为示例,实际价格请参考各API提供商最新定价。
成本优化建议
-
模型选择优化:
- 非关键任务使用更经济的模型(如gpt-4o-mini替代gpt-4o)
- 长文档处理可考虑使用支持长上下文的开源模型
-
调用策略优化:
- 合理设置
max_tokens参数,避免不必要的token消耗 - 使用缓存机制避免重复调用(可通过插件实现)
- 长对话场景优化上下文管理,只保留关键历史信息
- 合理设置
-
批量处理:
- 将多个小请求合并为批量请求,减少调用次数
自动化监控与告警
使用cron任务定期生成报告
创建一个bash脚本llm_monitor.sh:
#!/bin/bash
# 设置输出目录
REPORT_DIR="$HOME/llm_reports"
mkdir -p "$REPORT_DIR"
# 生成每日报告
llm logs --json -n 0 | llm -s "分析过去24小时的LLM API调用日志,生成监控报告,包括:1.调用总量变化 2.各模型使用占比 3.性能指标(响应时间、token消耗)异常 4.成本估算 5.优化建议。使用Markdown格式输出,适当使用表格和列表。" > "$REPORT_DIR/$(date +%Y%m%d)_daily_report.md"
# 检查是否有异常(响应时间超过3秒的调用)
ANOMALIES=$(sqlite3 "$(llm logs path)" "SELECT COUNT(*) FROM responses WHERE duration_ms > 3000 AND datetime_utc > datetime('now', '-24 hours');")
# 如果有异常,发送通知(这里使用简单的echo,实际可集成邮件或其他告警方式)
if [ "$ANOMALIES" -gt 0 ]; then
echo "发现$ANOMALIES次响应时间异常的API调用,请查看报告:$REPORT_DIR/$(date +%Y%m%d)_daily_report.md"
fi
添加执行权限并设置cron任务:
chmod +x llm_monitor.sh
# 每天凌晨2点执行
echo "0 2 * * * $HOME/llm_monitor.sh" | crontab -
设置阈值告警
可以使用SQL查询监控关键指标是否超过阈值,并通过邮件或其他方式发送告警:
#!/bin/bash
# 检查是否有响应时间超过5秒的调用
SLOW_CALLS=$(sqlite3 "$(llm logs path)" "SELECT COUNT(*) FROM responses WHERE duration_ms > 5000 AND datetime_utc > datetime('now', '-1 hours');")
if [ "$SLOW_CALLS" -gt 5 ]; then
# 发送告警邮件(需要配置mail命令)
echo "在过去1小时内发现$SLOW_CALLS次响应时间超过5秒的LLM调用,请检查系统性能。" | mail -s "LLM性能告警" your@email.com
fi
扩展监控功能
自定义工具监控token消耗
通过LLM的工具功能,可以创建一个自定义工具来实时监控token消耗:
创建文件token_monitor.py:
import time
from llm import Tool
def token_usage_stats(days: int = 7) -> str:
"""
生成过去N天的token使用统计报告。
Args:
days: 统计天数,默认为7天
Returns:
格式化的token使用统计报告
"""
from datetime import datetime, timedelta
import sqlite3
db_path = None
# 获取日志数据库路径
import subprocess
result = subprocess.run(['llm', 'logs', 'path'], capture_output=True, text=True)
db_path = result.stdout.strip()
if not db_path:
return "无法获取日志数据库路径"
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# 计算起始日期
start_date = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
# 查询统计数据
cursor.execute("""
SELECT
model,
COUNT(*) as call_count,
SUM(input_tokens) as total_input_tokens,
SUM(output_tokens) as total_output_tokens,
SUM(duration_ms) as total_duration_ms
FROM responses
WHERE datetime_utc >= ?
GROUP BY model
ORDER BY total_input_tokens + total_output_tokens DESC
""", (start_date,))
results = cursor.fetchall()
conn.close()
# 生成报告
report = f"过去{days}天LLM token使用统计报告 ({start_date} 至 {datetime.now().strftime('%Y-%m-%d')})\n\n"
report += "| 模型 | 调用次数 | 输入token | 输出token | 总token | 平均响应时间(ms) |\n"
report += "|------|----------|-----------|-----------|---------|------------------|\n"
for row in results:
model, call_count, input_t, output_t, duration = row
total_t = input_t + output_t
avg_duration = duration // call_count if call_count > 0 else 0
report += f"| {model} | {call_count} | {input_t} | {output_t} | {total_t} | {avg_duration} |\n"
return report
# 将函数注册为LLM工具
tools = [Tool.from_function(token_usage_stats)]
使用自定义工具:
llm --functions token_monitor.py "生成过去30天的token使用报告" --td
总结与展望
本文详细介绍了如何利用LLM自带的日志系统和扩展功能,构建完整的API调用监控方案。通过实施这些监控措施,你可以:
- 全面掌握LLM API的使用情况和性能表现
- 及时发现并解决性能瓶颈
- 有效控制API调用成本
- 优化模型选择和调用策略
未来,LLM监控系统可以进一步扩展,增加实时监控仪表盘、多维度对比分析和更智能的自动优化建议。通过持续监控和优化,将能够在保证业务效果的同时,最大化LLM投资回报率。
附录:常用命令参考
| 命令 | 说明 |
|---|---|
llm logs path | 查看日志数据库路径 |
llm logs status | 查看日志系统状态 |
llm logs on/off | 开启/关闭日志记录 |
llm logs -m <model> | 按模型筛选日志 |
llm logs --json -n 0 | 导出所有日志为JSON |
datasette "$(llm logs path)" | 使用Datasette分析日志 |
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



