diff --git a/src/chat/utils/statistic.py b/src/chat/utils/statistic.py index 2fa93c797..983a0c1d2 100644 --- a/src/chat/utils/statistic.py +++ b/src/chat/utils/statistic.py @@ -90,6 +90,18 @@ STD_TIME_COST_BY_MODULE = "std_time_costs_by_module" ONLINE_TIME = "online_time" TOTAL_MSG_CNT = "total_messages" MSG_CNT_BY_CHAT = "messages_by_chat" +TIME_COST_BY_TYPE = "time_costs_by_type" +TIME_COST_BY_USER = "time_costs_by_user" +TIME_COST_BY_MODEL = "time_costs_by_model" +TIME_COST_BY_MODULE = "time_costs_by_module" +AVG_TIME_COST_BY_TYPE = "avg_time_costs_by_type" +AVG_TIME_COST_BY_USER = "avg_time_costs_by_user" +AVG_TIME_COST_BY_MODEL = "avg_time_costs_by_model" +AVG_TIME_COST_BY_MODULE = "avg_time_costs_by_module" +STD_TIME_COST_BY_TYPE = "std_time_costs_by_type" +STD_TIME_COST_BY_USER = "std_time_costs_by_user" +STD_TIME_COST_BY_MODEL = "std_time_costs_by_model" +STD_TIME_COST_BY_MODULE = "std_time_costs_by_module" class OnlineTimeRecordTask(AsyncTask): @@ -418,7 +430,7 @@ class StatisticOutputTask(AsyncTask): stats[period_key][COST_BY_USER][user_id] += cost stats[period_key][COST_BY_MODEL][model_name] += cost stats[period_key][COST_BY_MODULE][module_name] += cost - + # 收集time_cost数据 time_cost = record.time_cost or 0.0 if time_cost > 0: # 只记录有效的time_cost @@ -427,8 +439,8 @@ class StatisticOutputTask(AsyncTask): stats[period_key][TIME_COST_BY_MODEL][model_name].append(time_cost) stats[period_key][TIME_COST_BY_MODULE][module_name].append(time_cost) break - - # 计算平均耗时和标准差 + + # 计算平均耗时和标准差 for period_key in stats: for category in [REQ_CNT_BY_TYPE, REQ_CNT_BY_USER, REQ_CNT_BY_MODEL, REQ_CNT_BY_MODULE]: time_cost_key = f"time_costs_by_{category.split('_')[-1]}" @@ -452,7 +464,6 @@ class StatisticOutputTask(AsyncTask): else: stats[period_key][avg_key][item_name] = 0.0 stats[period_key][std_key][item_name] = 0.0 - return stats @staticmethod @@ -687,7 +698,6 @@ class StatisticOutputTask(AsyncTask): data_fmt = "{:<32} {:>10} {:>12} {:>12} {:>12} {:>9.4f}¥ {:>10} {:>10}" output = [ - "按模型分类统计:", " 模型名称 调用次数 输入Token 输出Token Token总量 累计花费 平均耗时(秒) 标准差(秒)", ] for model_name, count in sorted(stats[REQ_CNT_BY_MODEL].items()): @@ -843,7 +853,7 @@ class StatisticOutputTask(AsyncTask):

按模型分类统计

- + {model_rows} diff --git a/src/common/database/sqlalchemy_models.py b/src/common/database/sqlalchemy_models.py index c0f8a9466..983bf7578 100644 --- a/src/common/database/sqlalchemy_models.py +++ b/src/common/database/sqlalchemy_models.py @@ -29,6 +29,8 @@ def get_string_field(max_length=255, **kwargs): return String(max_length, **kwargs) else: return Text(**kwargs) + + class SessionProxy: """线程安全的Session代理类,自动管理session生命周期""" @@ -155,11 +157,14 @@ class LLMUsage(Base): id = Column(Integer, primary_key=True, autoincrement=True) model_name = Column(get_string_field(100), nullable=False, index=True) + model_assign_name = Column(get_string_field(100), index=True) # 添加索引 + model_api_provider = Column(get_string_field(100), index=True) # 添加索引 user_id = Column(get_string_field(50), nullable=False, index=True) request_type = Column(get_string_field(50), nullable=False, index=True) endpoint = Column(Text, nullable=False) prompt_tokens = Column(Integer, nullable=False) completion_tokens = Column(Integer, nullable=False) + time_cost = Column(Float, nullable=True) total_tokens = Column(Integer, nullable=False) cost = Column(Float, nullable=False) status = Column(Text, nullable=False) @@ -167,6 +172,9 @@ class LLMUsage(Base): __table_args__ = ( Index('idx_llmusage_model_name', 'model_name'), + Index('idx_llmusage_model_assign_name', 'model_assign_name'), + Index('idx_llmusage_model_api_provider', 'model_api_provider'), + Index('idx_llmusage_time_cost', 'time_cost'), Index('idx_llmusage_user_id', 'user_id'), Index('idx_llmusage_request_type', 'request_type'), Index('idx_llmusage_timestamp', 'timestamp'), diff --git a/src/llm_models/utils_model.py b/src/llm_models/utils_model.py index 330fc6329..b7f9e79e5 100644 --- a/src/llm_models/utils_model.py +++ b/src/llm_models/utils_model.py @@ -148,6 +148,7 @@ class LLMRequest: model_info=model_info, model_usage=usage, user_id="system", + time_cost=time.time() - start_time, request_type=self.request_type, endpoint="/chat/completions", time_cost=time.time() - start_time, @@ -242,6 +243,7 @@ class LLMRequest: ) -> Tuple[str, Tuple[str, str, Optional[List[ToolCall]]]]: """执行单次请求""" # 模型选择和请求准备 + start_time = time.time() model_info, api_provider, client = self._select_model() processed_prompt = self._apply_content_obfuscation(prompt, api_provider) @@ -295,6 +297,7 @@ class LLMRequest: llm_usage_recorder.record_usage_to_database( model_info=model_info, model_usage=usage, + time_cost=time.time() - start_time, user_id="system", request_type=self.request_type, endpoint="/chat/completions", @@ -350,6 +353,7 @@ class LLMRequest: if usage := response.usage: llm_usage_recorder.record_usage_to_database( model_info=model_info, + time_cost=time.time() - start_time, model_usage=usage, user_id="system", request_type=self.request_type,
模型名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
模块名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)