add token log

This commit is contained in:
aaron 2025-04-27 15:18:17 +08:00
parent 303f938bd7
commit 4958b031c2
6 changed files with 415 additions and 18 deletions

View File

@ -490,8 +490,45 @@ class CryptoAgent:
print(f"分析结果已保存到:{results_file}") print(f"分析结果已保存到:{results_file}")
# 导出 DeepSeek API token 使用情况
self._export_token_usage()
return results return results
def _export_token_usage(self) -> None:
"""
导出 DeepSeek API token 使用情况
"""
try:
# 每天导出一次详细的JSON数据
today = datetime.now().strftime("%Y%m%d")
token_usage_dir = os.path.join(self.data_config['storage_path'], 'token_usage')
os.makedirs(token_usage_dir, exist_ok=True)
json_file = os.path.join(token_usage_dir, f"deepseek_token_usage_{today}.json")
# 如果文件不存在,导出一次
if not os.path.exists(json_file):
exported_file = self.deepseek_api.export_token_usage(json_file)
if exported_file:
print(f"DeepSeek API token 使用情况已导出到:{exported_file}")
# 每次都导出CSV格式的统计数据
csv_file = os.path.join(token_usage_dir, f"deepseek_token_usage_{today}.csv")
self.deepseek_api.export_token_usage(csv_file, "csv")
# 输出当前使用情况统计
stats = self.deepseek_api.get_token_usage_stats()
print(f"DeepSeek API token 使用统计:")
print(f"- 总调用次数: {stats['total_calls']}")
print(f"- 总token数: {stats['total_tokens']}")
print(f"- 输入token: {stats['total_prompt_tokens']}")
print(f"- 输出token: {stats['total_completion_tokens']}")
print(f"- 平均每次调用: {stats['average_tokens_per_call']:.2f} tokens")
except Exception as e:
print(f"导出 token 使用情况时出错: {e}")
def start_agent(self, run_once: bool = False) -> None: def start_agent(self, run_once: bool = False) -> None:
""" """
启动智能体 启动智能体
@ -504,6 +541,8 @@ class CryptoAgent:
try: try:
if run_once: if run_once:
self.run_analysis_cycle() self.run_analysis_cycle()
# 导出最终的token使用情况
self._export_token_usage()
else: else:
while True: while True:
self.run_analysis_cycle() self.run_analysis_cycle()
@ -515,11 +554,15 @@ class CryptoAgent:
except KeyboardInterrupt: except KeyboardInterrupt:
print("\n智能体已停止") print("\n智能体已停止")
# 导出最终的token使用情况
self._export_token_usage()
except Exception as e: except Exception as e:
print(f"智能体运行时出错: {e}") print(f"智能体运行时出错: {e}")
import traceback import traceback
traceback.print_exc() traceback.print_exc()
# 发生错误时也尝试导出token使用情况
self._export_token_usage()
def send_notifications(self, symbol: str, analysis_data: Dict[str, Any]) -> bool: def send_notifications(self, symbol: str, analysis_data: Dict[str, Any]) -> bool:
""" """

View File

@ -1,9 +1,20 @@
import os import os
import json import json
import requests import requests
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional, Tuple
import time import time
import logging
import datetime
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("deepseek_token_usage.log"),
logging.StreamHandler()
]
)
class DeepSeekAPI: class DeepSeekAPI:
"""DeepSeek API交互类用于进行市场分析和预测""" """DeepSeek API交互类用于进行市场分析和预测"""
@ -23,6 +34,17 @@ class DeepSeekAPI:
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": f"Bearer {api_key}" "Authorization": f"Bearer {api_key}"
} }
# Token 使用统计
self.token_usage = {
"total_prompt_tokens": 0,
"total_completion_tokens": 0,
"total_tokens": 0,
"calls": []
}
# 创建日志记录器
self.logger = logging.getLogger("DeepSeekAPI")
def analyze_market_data(self, market_data: Dict[str, Any]) -> Dict[str, Any]: def analyze_market_data(self, market_data: Dict[str, Any]) -> Dict[str, Any]:
""" """
@ -41,10 +63,16 @@ class DeepSeekAPI:
prompt = self._build_market_analysis_prompt(formatted_data) prompt = self._build_market_analysis_prompt(formatted_data)
# 调用API获取分析 # 调用API获取分析
response = self._call_api(prompt) response, usage = self._call_api(prompt, task_type="市场分析", symbol=market_data.get("symbol", "未知"))
# 解析响应 # 解析响应
return self._parse_analysis_response(response) result = self._parse_analysis_response(response)
# 添加token使用信息
if usage:
result["_token_usage"] = usage
return result
def predict_price_trend(self, symbol: str, historical_data: Dict[str, Any]) -> Dict[str, Any]: def predict_price_trend(self, symbol: str, historical_data: Dict[str, Any]) -> Dict[str, Any]:
""" """
@ -64,10 +92,16 @@ class DeepSeekAPI:
prompt = self._build_price_prediction_prompt(symbol, formatted_data) prompt = self._build_price_prediction_prompt(symbol, formatted_data)
# 调用API获取预测 # 调用API获取预测
response = self._call_api(prompt) response, usage = self._call_api(prompt, task_type="价格预测", symbol=symbol)
# 解析响应 # 解析响应
return self._parse_prediction_response(response) result = self._parse_prediction_response(response)
# 添加token使用信息
if usage:
result["_token_usage"] = usage
return result
def generate_trading_strategy(self, symbol: str, analysis_result: Dict[str, Any], risk_level: str) -> Dict[str, Any]: def generate_trading_strategy(self, symbol: str, analysis_result: Dict[str, Any], risk_level: str) -> Dict[str, Any]:
""" """
@ -85,21 +119,112 @@ class DeepSeekAPI:
prompt = self._build_trading_strategy_prompt(symbol, analysis_result, risk_level) prompt = self._build_trading_strategy_prompt(symbol, analysis_result, risk_level)
# 调用API获取策略 # 调用API获取策略
response = self._call_api(prompt) response, usage = self._call_api(prompt, task_type="交易策略", symbol=symbol)
# 解析响应 # 解析响应
return self._parse_strategy_response(response) result = self._parse_strategy_response(response)
# 添加token使用信息
if usage:
result["_token_usage"] = usage
return result
def _call_api(self, prompt: str) -> Dict[str, Any]: def get_token_usage_stats(self) -> Dict[str, Any]:
"""
获取Token使用统计信息
Returns:
包含使用统计的字典
"""
return {
"total_prompt_tokens": self.token_usage["total_prompt_tokens"],
"total_completion_tokens": self.token_usage["total_completion_tokens"],
"total_tokens": self.token_usage["total_tokens"],
"total_calls": len(self.token_usage["calls"]),
"average_tokens_per_call": self.token_usage["total_tokens"] / len(self.token_usage["calls"]) if self.token_usage["calls"] else 0,
"detailed_calls": self.token_usage["calls"][-10:] # 仅返回最近10次调用详情
}
def export_token_usage(self, file_path: str = None, format: str = "json") -> str:
"""
导出Token使用数据到文件
Args:
file_path: 文件路径如果为None则自动生成
format: 导出格式支持'json''csv'
Returns:
导出文件的路径
"""
if file_path is None:
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
file_path = f"deepseek_token_usage_{timestamp}.{format}"
try:
if format.lower() == "json":
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(self.token_usage, f, indent=2, ensure_ascii=False)
elif format.lower() == "csv":
import csv
with open(file_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
# 写入表头
writer.writerow([
"timestamp", "task_type", "symbol", "model",
"prompt_tokens", "completion_tokens", "total_tokens",
"duration_seconds"
])
# 写入数据
for call in self.token_usage["calls"]:
writer.writerow([
call.get("timestamp", ""),
call.get("task_type", ""),
call.get("symbol", ""),
call.get("model", ""),
call.get("prompt_tokens", 0),
call.get("completion_tokens", 0),
call.get("total_tokens", 0),
call.get("duration_seconds", 0)
])
# 写入总计
writer.writerow([])
writer.writerow([
f"总计 (调用次数: {len(self.token_usage['calls'])})",
"", "", "",
self.token_usage["total_prompt_tokens"],
self.token_usage["total_completion_tokens"],
self.token_usage["total_tokens"],
""
])
else:
raise ValueError(f"不支持的格式: {format},仅支持 'json''csv'")
self.logger.info(f"Token使用数据已导出到: {file_path}")
return file_path
except Exception as e:
error_msg = f"导出Token使用数据时出错: {e}"
self.logger.error(error_msg)
return ""
def _call_api(self, prompt: str, task_type: str = "未知任务", symbol: str = "未知") -> Tuple[Dict[str, Any], Dict[str, Any]]:
""" """
调用DeepSeek API 调用DeepSeek API
Args: Args:
prompt: 提示词 prompt: 提示词
task_type: 任务类型
symbol: 交易对符号
Returns: Returns:
API响应 (API响应, token使用信息)
""" """
usage_info = {}
try: try:
endpoint = f"{self.base_url}/chat/completions" endpoint = f"{self.base_url}/chat/completions"
@ -113,14 +238,48 @@ class DeepSeekAPI:
"max_tokens": 2000 "max_tokens": 2000
} }
start_time = time.time()
response = requests.post(endpoint, headers=self.headers, json=payload) response = requests.post(endpoint, headers=self.headers, json=payload)
response.raise_for_status() response.raise_for_status()
response_data = response.json()
end_time = time.time()
return response.json() # 记录token使用情况
if 'usage' in response_data:
prompt_tokens = response_data['usage'].get('prompt_tokens', 0)
completion_tokens = response_data['usage'].get('completion_tokens', 0)
total_tokens = response_data['usage'].get('total_tokens', 0)
usage_info = {
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"total_tokens": total_tokens,
"task_type": task_type,
"symbol": symbol,
"model": self.model,
"timestamp": datetime.datetime.now().isoformat(),
"duration_seconds": round(end_time - start_time, 2)
}
# 更新总计
self.token_usage["total_prompt_tokens"] += prompt_tokens
self.token_usage["total_completion_tokens"] += completion_tokens
self.token_usage["total_tokens"] += total_tokens
self.token_usage["calls"].append(usage_info)
# 记录到日志
self.logger.info(
f"DeepSeek API调用 - 任务: {task_type}, 符号: {symbol}, "
f"输入tokens: {prompt_tokens}, 输出tokens: {completion_tokens}, "
f"总tokens: {total_tokens}, 耗时: {round(end_time - start_time, 2)}"
)
return response_data, usage_info
except Exception as e: except Exception as e:
print(f"调用DeepSeek API时出错: {e}") error_msg = f"调用DeepSeek API时出错: {e}"
return {} self.logger.error(error_msg)
return {}, usage_info
def _format_market_data(self, market_data: Dict[str, Any]) -> str: def _format_market_data(self, market_data: Dict[str, Any]) -> str:
""" """
@ -273,7 +432,8 @@ class DeepSeekAPI:
return {"error": "API响应格式不正确", "raw_response": response} return {"error": "API响应格式不正确", "raw_response": response}
except Exception as e: except Exception as e:
print(f"解析分析响应时出错: {e}") error_msg = f"解析分析响应时出错: {e}"
self.logger.error(error_msg)
return {"error": str(e), "raw_response": response} return {"error": str(e), "raw_response": response}
def _parse_prediction_response(self, response: Dict[str, Any]) -> Dict[str, Any]: def _parse_prediction_response(self, response: Dict[str, Any]) -> Dict[str, Any]:

View File

@ -13,17 +13,17 @@ deepseek:
crypto: crypto:
base_currencies: base_currencies:
# - "BTC" # - "BTC"
- "ETH" # - "ETH"
- "BNB" # - "BNB"
- "SOL" # - "SOL"
# - "ADA" - "SUI"
quote_currency: "USDT" quote_currency: "USDT"
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
# 数据设置 # 数据设置
data: data:
storage_path: "./cryptoai/data" storage_path: "./cryptoai/data"
historical_days: 30 historical_days: 180
update_interval: 60 # 数据更新间隔(分钟) update_interval: 60 # 数据更新间隔(分钟)
# Agent设置 # Agent设置

View File

@ -0,0 +1,194 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
DeepSeek API Token使用情况分析工具
"""
import os
import sys
import argparse
import json
from typing import Dict, Any
import pandas as pd
from datetime import datetime
# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from api.deepseek_api import DeepSeekAPI
from utils.config_loader import ConfigLoader
def get_deepseek_api() -> DeepSeekAPI:
"""
获取已配置的DeepSeekAPI实例
"""
config_loader = ConfigLoader()
deepseek_config = config_loader.get_deepseek_config()
if not deepseek_config or 'api_key' not in deepseek_config:
print("错误: 未找到DeepSeek API配置或API密钥")
sys.exit(1)
return DeepSeekAPI(
api_key=deepseek_config['api_key'],
model=deepseek_config.get('model', 'deepseek-moe-16b-chat')
)
def show_token_usage_stats():
"""
显示Token使用统计信息
"""
api = get_deepseek_api()
stats = api.get_token_usage_stats()
print("\n===== DeepSeek API Token使用统计 =====")
print(f"总输入Tokens: {stats['total_prompt_tokens']:,}")
print(f"总输出Tokens: {stats['total_completion_tokens']:,}")
print(f"总Tokens: {stats['total_tokens']:,}")
print(f"API调用次数: {stats['total_calls']}")
print(f"平均每次调用Tokens: {stats['average_tokens_per_call']:.2f}")
if stats['total_calls'] > 0:
print("\n最近调用记录:")
for call in stats['detailed_calls']:
print(f" - {call['timestamp']} | {call['symbol']} | {call['task_type']} | "
f"输入: {call['prompt_tokens']} | 输出: {call['completion_tokens']} | "
f"总计: {call['total_tokens']} | 耗时: {call['duration_seconds']}")
print("\n注意: 这些统计数据仅反映当前程序运行期间的使用情况")
def export_token_usage(format_type: str = "json", output_path: str = None):
"""
导出Token使用数据
Args:
format_type: 导出格式'json''csv'
output_path: 输出文件路径
"""
api = get_deepseek_api()
if output_path is None:
# 如果未指定路径,则使用默认路径
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = f"deepseek_token_usage_{timestamp}.{format_type}"
file_path = api.export_token_usage(output_path, format_type)
if file_path:
print(f"\nToken使用数据已导出到: {file_path}")
else:
print("\n导出Token使用数据失败")
def analyze_token_usage(json_file: str = None):
"""
分析Token使用数据并显示统计
Args:
json_file: JSON格式的Token使用数据文件
"""
try:
# 加载数据
if json_file and os.path.exists(json_file):
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
else:
# 使用当前内存中的数据
api = get_deepseek_api()
data = api.token_usage
if not data or not data.get('calls'):
print("没有可用的Token使用数据进行分析")
return
# 转换为DataFrame进行分析
df = pd.DataFrame(data['calls'])
# 按任务类型分析
task_analysis = df.groupby('task_type').agg({
'prompt_tokens': ['sum', 'mean'],
'completion_tokens': ['sum', 'mean'],
'total_tokens': ['sum', 'mean', 'count']
})
# 按符号(交易对)分析
symbol_analysis = df.groupby('symbol').agg({
'total_tokens': ['sum', 'mean', 'count']
})
# 计算总体统计
total_tokens = data['total_tokens']
total_calls = len(data['calls'])
# 显示分析结果
print("\n===== DeepSeek API Token使用分析 =====")
print(f"总调用次数: {total_calls}")
print(f"总Token使用: {total_tokens:,}")
print(f"平均每次调用Token: {total_tokens / total_calls if total_calls else 0:.2f}")
print("\n--- 按任务类型分析 ---")
for task, stats in task_analysis.iterrows():
calls = stats[('total_tokens', 'count')]
total = stats[('total_tokens', 'sum')]
avg = stats[('total_tokens', 'mean')]
print(f"{task}: {calls}次调用, 共{total:,}tokens, 平均{avg:.2f}tokens/次")
print("\n--- 按交易对分析 ---")
for symbol, stats in symbol_analysis.iterrows():
calls = stats[('total_tokens', 'count')]
total = stats[('total_tokens', 'sum')]
avg = stats[('total_tokens', 'mean')]
print(f"{symbol}: {calls}次调用, 共{total:,}tokens, 平均{avg:.2f}tokens/次")
except Exception as e:
print(f"分析Token使用数据时出错: {e}")
def main():
"""主函数"""
parser = argparse.ArgumentParser(description="DeepSeek API Token使用情况分析工具")
subparsers = parser.add_subparsers(dest="command", help="命令")
# 显示统计信息
show_parser = subparsers.add_parser("show", help="显示Token使用统计")
# 导出使用数据
export_parser = subparsers.add_parser("export", help="导出Token使用数据")
export_parser.add_argument(
"--format", "-f",
choices=["json", "csv"],
default="json",
help="导出格式 (默认: json)"
)
export_parser.add_argument(
"--output", "-o",
help="输出文件路径"
)
# 分析使用数据
analyze_parser = subparsers.add_parser("analyze", help="分析Token使用数据")
analyze_parser.add_argument(
"--input", "-i",
help="输入JSON文件路径如果未指定则使用当前内存中的数据"
)
args = parser.parse_args()
if args.command == "show":
show_token_usage_stats()
elif args.command == "export":
export_token_usage(args.format, args.output)
elif args.command == "analyze":
analyze_token_usage(args.input)
else:
# 默认显示统计信息
show_token_usage_stats()
if __name__ == "__main__":
main()