TradingAgents-CN 使用统计与模型定价配置实战指南:从成本计算原理到多维计费分析
【免费下载链接】TradingAgents-CN基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN
导读
本文聚焦 TradingAgents-CN(基于多智能体 LLM 的中文金融交易框架)内置的使用统计与定价配置能力,完整讲解"为每个大模型配置输入/输出 Token 价格、自动记录每次 API 调用成本、按供应商/模型/日期多维度分析计费"的完整链路。读完本文,你将掌握模型定价字段的含义与配置方法、成本计算公式的底层实现、使用统计服务与 API 端点的调用方式、前端使用统计页面的操作要点,以及成本控制与数据管理的最佳实践,可直接用于日常运维中的 LLM 成本监控与模型选型决策。
功能全景:一个可量化的多智能体成本管理体系
TradingAgents-CN 以多个 LLM 智能体协作完成股票分析任务,每次调用大模型都会产生 Token 消耗与费用。为了让开发者清楚掌握资金流向,项目实现了完整的三层能力(见 功能文档):
- 模型定价配置:为每个大模型配置输入/输出 Token 单价;
- 使用统计:自动记录每次 API 调用的 Token 与成本,并实时聚合;
- 计费分析:按供应商、模型、日期三个维度分析成本分布。
从实现总结可以看到,这套功能的后端由UsageStatisticsService服务层与usage_statistics路由组成,数据落库 MongoDB 的token_usage集合;前端则由UsageStatistics.vue统计页面与增强后的配置管理页面组成,技术栈为 FastAPI + MongoDB + Pydantic + Vue 3 + Element Plus + ECharts。
整体数据流如下:
用户操作(前端页面 UsageStatistics.vue / ConfigManagement.vue) ↓ API 调用(frontend/src/api/usage.ts) ↓ 后端路由(app/routers/usage_statistics.py,JWT 认证) ↓ 服务层(app/services/usage_statistics_service.py) ↓ MongoDB 数据库(token_usage 集合) ↓ 返回数据 → 前端渲染(概览卡片 / ECharts 图表 / 记录表格)模型定价配置
数据模型:LLMConfig 的定价字段
定价信息与模型配置一体存储。在 app/models/config.py 中,LLMConfig模型在原有字段基础上扩展了三个定价字段:
class LLMConfig(BaseModel): provider: str = Field(default="openai", description="供应商标识(支持动态添加)") model_name: str = Field(..., description="模型名称/代码") # ... 原有字段(max_tokens、temperature、timeout、enabled 等)... input_price_per_1k: Optional[float] = Field(None, description="输入token价格(每1000个token)") output_price_per_1k: Optional[float] = Field(None, description="输出token价格(每1000个token)") currency: str = Field(default="CNY", description="货币单位(CNY/USD/EUR)")参数说明:
| 字段 | 类型 | 默认值 | 含义 |
|---|---|---|---|
input_price_per_1k | float | None | 每 1000 个输入 token 的价格 |
output_price_per_1k | float | None | 每 1000 个输出 token 的价格 |
currency | str | "CNY" | 货币单位,支持 CNY / USD / EUR |
在 API 请求层,LLMConfigRequest同步携带了这三个定价字段,因此通过配置管理接口创建或更新大模型配置时即可一并写入定价。底层 tradingagents/config/usage_models.py 中的PricingConfig数据类(provider、model_name、input_price_per_1k、output_price_per_1k、currency)则对应配置文件形态的定价记录。
界面操作:模型卡片与编辑对话框
在"配置管理 > 大模型配置"中,每个模型卡片会直接显示定价信息,便于快速核对:
┌─────────────────────────────────────┐ │ 🖥️ qwen-max ✅ 启用 │ ├─────────────────────────────────────┤ │ Token: 4000 │ │ 温度: 0.7 │ │ 超时: 60s │ ├─────────────────────────────────────┤ │ 💰 定价: │ │ 输入: 0.0200 CNY/1K │ │ 输出: 0.0600 CNY/1K │ └─────────────────────────────────────┘点击"编辑"按钮弹出对话框(对应 LLMConfigDialog.vue),可配置:
- 输入价格(
input_price_per_1k):每 1000 个输入 token 的价格; - 输出价格(
output_price_per_1k):每 1000 个输出 token 的价格; - 货币单位(
currency):CNY(人民币)/ USD(美元)/ EUR(欧元)。
卡片展示逻辑位于 ConfigManagement.vue,定价字段未配置时按0.0处理,不会影响其他模型配置的正常保存与启用。
定价配置的落盘与同步机制
定价配置保存后,app/core/config_bridge.py 中的_sync_pricing_config(llm_configs)会将启用的模型定价同步到config/pricing.json,供底层 TradingAgents 核心库读取:
pricing_config = { "provider": llm_config.provider, "model_name": llm_config.model_name, "input_price_per_1k": llm_config.input_price_per_1k or 0.0, "output_price_per_1k": llm_config.output_price_per_1k or 0.0, "currency": llm_config.currency or "CNY" }该函数只同步enabled=True的模型,且通过or 0.0兜底,保证未定价的模型写入0.0而不是null;同时提供sync_pricing_config_now()在配置更新后异步实时同步。这一机制保证了"数据库中的模型配置"与"底层核心库使用的 pricing.json"始终一致,是成本计算能够生效的前提。
使用统计界面
访问入口
使用统计页面挂载在设置模块下,路由定义见 frontend/src/router/index.ts(path: 'usage',requiresAuth: true)。访问方式有两种:
- 通过导航菜单:登录系统 → 点击"设置" → 选择"使用统计";
- 直接访问前端地址:
http://localhost:5173/settings/usage(前端开发服务器默认端口)。
对应页面组件为 frontend/src/views/Settings/UsageStatistics.vue,顶部提供时间范围选择(最近 7 / 30 / 90 天)与刷新按钮。
统计概览:四个关键指标
页面顶部以卡片形式展示(UsageStatistics.vue):
- 总请求数;
- 总输入 Token;
- 总输出 Token;
- 总成本(按货币分组显示,例如
0.0200 ¥,支持多货币并存)。
其中总成本不再只依赖单一的total_cost字段,而是遍历cost_by_currency按货币符号分别展示,这对应后端统计模型中的"按货币统计成本"设计。
图表分析:三个维度
页面中部使用 ECharts 渲染三张图表:
- 按供应商统计(饼图):展示各供应商的成本占比,快速识别主要成本来源;
- 按模型统计(柱状图):展示成本排名前 10 的模型,便于横向对比不同模型的使用成本;
- 每日成本趋势(折线图):展示每日成本变化曲线,用于分析成本随时间的走势与异常波动。
使用记录表格
页面底部为详细的使用记录表格,逐条列出每次 API 调用:时间、供应商、模型、输入/输出 Token、成本、分析类型、会话 ID。支持分页加载(limit默认 100,最大 1000)与"清理旧记录"操作,避免历史数据无限膨胀。
后端技术实现:服务、API 与数据模型
使用统计服务(UsageStatisticsService)
核心服务实现位于 app/services/usage_statistics_service.py,类方法清单如下:
class UsageStatisticsService: async def add_usage_record(record: UsageRecord) -> bool # 添加使用记录 async def get_usage_records(provider, model_name, start_date, end_date, limit=100) -> List[UsageRecord] async def get_usage_statistics(days=7, provider, model_name) -> UsageStatistics async def get_cost_by_provider(days=7) -> Dict[str, float] # 按供应商统计成本 async def get_cost_by_model(days=7) -> Dict[str, float] # 按模型统计成本 async def get_daily_cost(days=7) -> Dict[str, float] # 每日成本统计 async def delete_old_records(days=90) -> int # 删除旧记录实现要点(可从源码确认):
- 集合与存储:服务统一使用 MongoDB 的
token_usage集合,与 TradingAgents 核心库保持一致的命名;add_usage_record通过record.model_dump(exclude={"id"})序列化后写入。 - 多维聚合逻辑:
get_usage_statistics在内存中通过defaultdict同时维护by_provider、by_model、by_date三套聚合(每套含requests、input_tokens、output_tokens、cost及按货币细分的cost_by_currency);by_model的键采用"{provider}/{model_name}"格式,避免不同供应商的同名模型混淆;by_date通过截取时间戳前 10 位(YYYY-MM-DD)实现按天分组。 - 查询过滤:
get_usage_records与get_usage_statistics均支持按provider、model_name过滤,统计接口还支持按days限定时间窗口,记录查询按timestamp倒序返回。 - 数据保留:
delete_old_records(days=90)删除早于now - days的记录,用于定期清理历史数据。
API 端点一览
路由定义见 app/routers/usage_statistics.py,全部挂载在/api/usage前缀下,并在 app/main.py 中通过app.include_router(usage_statistics.router, tags=["usage-statistics"])注册进 FastAPI 应用:
| 方法 | 端点 | 参数 | 说明 |
|---|---|---|---|
| GET | /api/usage/records | provider、model_name、start_date、end_date、limit(1-1000) | 获取使用记录(按时间倒序) |
| GET | /api/usage/statistics | days(1-365)、provider、model_name | 获取多维使用统计 |
| GET | /api/usage/cost/by-provider | days(1-365) | 按供应商统计成本 |
| GET | /api/usage/cost/by-model | days(1-365) | 按模型统计成本 |
| GET | /api/usage/cost/daily | days(1-365) | 每日成本统计 |
| DELETE | /api/usage/records/old | days(30-365) | 删除旧记录,返回deleted_count |
安全细节:所有端点都通过Depends(get_current_user)要求 JWT 登录认证(auth_db);days被约束在 1-365,limit被约束在 1-1000,DELETE /records/old的保留天数被约束在 30-365,从参数层面防止越权或误操作。
数据模型:UsageRecord 与 UsageStatistics
使用记录模型 UsageRecord:
class UsageRecord(BaseModel): """使用记录""" id: Optional[str] = Field(None, description="记录ID") timestamp: str = Field(..., description="时间戳") provider: str = Field(..., description="供应商") model_name: str = Field(..., description="模型名称") input_tokens: int = Field(..., description="输入token数") output_tokens: int = Field(..., description="输出token数") cost: float = Field(..., description="成本") currency: str = Field(default="CNY", description="货币单位") session_id: str = Field(..., description="会话ID") analysis_type: str = Field(default="stock_analysis", description="分析类型") stock_code: Optional[str] = Field(None, description="股票代码")统计模型 UsageStatistics:
class UsageStatistics(BaseModel): """使用统计""" total_requests: int = Field(default=0, description="总请求数") total_input_tokens: int = Field(default=0, description="总输入token数") total_output_tokens: int = Field(default=0, description="总输出token数") total_cost: float = Field(default=0.0, description="总成本(已废弃,使用 cost_by_currency)") cost_by_currency: Dict[str, float] = Field(default_factory=dict, description="按货币统计的成本") by_provider: Dict[str, Any] = Field(default_factory=dict, description="按供应商统计") by_model: Dict[str, Any] = Field(default_factory=dict, description="按模型统计") by_date: Dict[str, Any] = Field(default_factory=dict, description="按日期统计")注意total_cost字段已标注"已废弃",取而代之的是cost_by_currency——当系统内同时存在 CNY 与 USD 定价的模型时,成本会按货币分别累加,避免把不同币种直接相加造成错误。这是阅读统计响应时需要留意的关键差异。
成本计算原理与自动记录链路
成本计算公式
按 功能文档 中的说明与 analysis_service.py 的实现:
成本 = (输入 tokens / 1000) × 输入价格 + (输出 tokens / 1000) × 输出价格即:输入与输出 Token 分别按各自单价折算为"每 1K Token"的费用后求和。示例:若某次调用消耗输入 2000 tokens、输出 1000 tokens,模型定价为输入 0.02 CNY/1K、输出 0.06 CNY/1K,则成本为(2000/1000)×0.02 + (1000/1000)×0.06 = 0.10元。
自动记录:分析完成后的埋点
每次股票分析完成后,analysis_service.py 的_record_token_usage会自动完成"取数 → 定价 → 计算 → 入库"的完整链路:
# 1. 从分析结果提取 token 使用量(无数据时按分析类型估算) input_tokens = result.tokens_used // 2 if result.tokens_used > 0 else 0 output_tokens = result.tokens_used - input_tokens if result.tokens_used > 0 else 0 if result.tokens_used == 0: input_tokens, output_tokens = 2000, 1000 # 默认估算 # 2. 查找对应 LLM 配置,取定价字段 cost = (input_tokens / 1000 * input_price) + (output_tokens / 1000 * output_price) # 3. 组装 UsageRecord 并写入 MongoDB usage_record = UsageRecord( timestamp=datetime.now().isoformat(), provider=provider, model_name=model_name, input_tokens=input_tokens, output_tokens=output_tokens, cost=cost, currency=currency, session_id=task.task_id, analysis_type="stock_analysis", stock_code=task.symbol ) await self.usage_service.add_usage_record(usage_record)几点需要说明的事实与限制:
- Token 来源:当前实现优先从 LLM 响应中提取实际 token 使用量(
result.tokens_used);若拿不到,则使用估算值(输入 2000 / 输出 1000)。因此统计数字在部分场景下是估算结果,仅供参考,不代表供应商账单的精确值。 - 无定价时的行为:若模型中未配置
input_price_per_1k/output_price_per_1k,价格按0.0参与计算,该次调用成本记为0,不影响整体流程。 - 货币单位:成本记录携带
currency字段,默认 CNY,统计时按货币分组展示。 - 数据延迟:统计基于 MongoDB 中的历史记录实时聚合,数据写入与查询之间存在几秒延迟,属于正常现象。
成本计算的测试验证
仓库提供了成本计算正确性的验证用例 tests/test_deepseek_cost_calculation.py,以 DeepSeek(输入 0.0014/1K、输出 0.0028/1K)为例,断言计算误差小于0.000001:
expected_cost = (input_tokens / 1000) * 0.0014 + (output_tokens / 1000) * 0.0028 # cost == expected_cost(误差 < 1e-6)其中一组用例直接采用真实分析场景的 token 数(输入 2617 / 输出 312),说明该公式已用真实调用数据校准过。此外 examples/token_tracking_demo.py 提供display_pricing_info()演示函数,可按供应商分组打印当前定价配置(输入/输出单价),适合在配置完成后快速核对。
前端调用与 API 使用示例
前端 API 封装
前端封装位于 frontend/src/api/usage.ts,提供了与后端一一对应的 6 个函数:
// 获取使用统计 export function getUsageStatistics(params?: { days?: number provider?: string model_name?: string }): Promise<ApiResponse<UsageStatistics>> { return ApiClient.get<UsageStatistics>('/api/usage/statistics', params) } // 按供应商统计成本 export function getCostByProvider(days: number = 7) { /* GET /api/usage/cost/by-provider */ } // 按模型统计成本 export function getCostByModel(days: number = 7) { /* GET /api/usage/cost/by-model */ } // 每日成本统计 export function getDailyCost(days: number = 7) { /* GET /api/usage/cost/daily */ } // 获取使用记录(支持 provider/model_name/start_date/end_date/limit) export function getUsageRecords(params?) { /* GET /api/usage/records */ } // 删除旧记录 export function deleteOldRecords(days: number = 90) { /* DELETE /api/usage/records/old */ }通过 API 配置模型定价
按 功能文档 的示例,可通过配置服务更新模型定价(对应LLMConfigRequest中的定价字段):
# 通过 API 更新模型配置(定价字段与模型配置一起提交) llm_config = { "provider": "dashscope", "model_name": "qwen-max", "input_price_per_1k": 0.02, # 2分/1K tokens "output_price_per_1k": 0.06, # 6分/1K tokens "currency": "CNY" } await config_service.update_llm_config(llm_config)查询使用统计
# 获取最近 7 天的统计 stats = await usage_statistics_service.get_usage_statistics(days=7) print(f"总请求数: {stats.total_requests}") print(f"总成本: ¥{stats.total_cost:.4f}") # 按供应商统计 for provider, data in stats.by_provider.items(): print(f"{provider}: ¥{data['cost']:.4f}")注意:当存在多币种记录时,应优先遍历stats.cost_by_currency查看各币种成本,而不是依赖已废弃的total_cost。
前端调用示例
// 获取使用统计(前端组件内部调用) import { getUsageStatistics } from '@/api/usage' const stats = await getUsageStatistics({ days: 7 }) console.log('总成本:', stats.data.data.total_cost)最佳实践与运维建议
定价配置建议
- 及时更新:供应商调整价格后及时更新对应模型的定价配置,避免统计失真;
- 统一货币:建议统一使用人民币(CNY)便于汇总统计;若必须混用多币种,请利用
cost_by_currency分组查看; - 精确配置:价格精确到小数点后 4 位(如
0.0200),前端卡片按 4 位小数展示。
成本控制
- 定期查看:每周查看使用统计(7 / 30 / 90 天时间范围一键切换),了解成本趋势;
- 识别高成本:通过"按模型统计"柱状图快速定位成本最高的模型,通过"按供应商统计"饼图判断成本来源;
- 优化选择:结合分析质量与成本,在低价模型与高价模型之间做取舍(可参考配置中的模型能力分级字段辅助决策)。
数据管理
- 定期清理:通过
DELETE /api/usage/records/old?days=90清理 90 天前的旧记录,或直接在统计页面点击"清理旧记录"(保留天数下限 30 天); - 导出备份:重要数据可调用
GET /api/usage/records分批导出备份; - 监控异常:关注每日成本趋势折线图,发现成本异常增长时及时排查(如某供应商配额耗尽导致的频繁重试)。
安全与注意事项
安全说明
- 使用记录存储在 MongoDB 的
token_usage集合中; - 所有统计与记录接口均要求登录认证(JWT),只有登录用户可查看统计数据;
- 定价信息与模型配置一体存储于 MongoDB,随配置权限体系受控;
- 支持按用户权限控制访问,接口层统一走
get_current_user依赖校验。
注意事项
- 自动记录:TradingAgents 核心库与分析服务会自动记录每次 API 调用,无需手动埋点;
- 成本计算:
成本 = (输入 tokens / 1000) × 输入价格 + (输出 tokens / 1000) × 输出价格,与测试用例中的公式一致; - 货币转换:系统不自动转换货币,请手动配置统一货币;多币种并存时按货币分组统计;
- 数据延迟:统计数据可能存在几秒延迟,实时性敏感场景需自行权衡;
- Token 估算:在拿不到 LLM 响应中的实际 token 数时,系统使用默认估算值(输入 2000 / 输出 1000),此时成本仅供参考。
未来计划
从 功能文档 与实现总结看,该模块规划中的增强方向包括:成本预警功能、成本预算管理、更多图表类型、导出统计报表(Excel/PDF)、自定义时间范围、成本优化建议、多用户成本分摊、实时成本监控。
延伸阅读
- 功能文档:使用统计与定价配置
- 实现总结:使用统计与定价配置功能
- 使用统计前端访问指南
- 使用统计快速测试说明
- 模型定价指南
- Token 跟踪指南
- 货币单位配置指南
【免费下载链接】TradingAgents-CN基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考