""" 使用量统计以及数据上报功能实现 """ import hashlib import json import logging import requests import pkg.utils.context import pkg.utils.updater class DataGatherer: """数据收集器""" usage = {} """各api-key的使用量 以key值md5为key,{ "text": { "text-davinci-003": 文字量:int, }, "image": { "256x256": 图片数量:int, } }为值的字典""" version_str = "undetermined" def __init__(self): self.load_from_db() try: self.version_str = pkg.utils.updater.get_current_tag() # 从updater模块获取版本号 except: pass def report_to_server(self, subservice_name: str, count: int): """向中央服务器报告使用量 只会报告此次请求的使用量,不会报告总量。 不包含除版本号、使用类型、使用量以外的任何信息,仅供开发者分析使用情况。 """ try: config = pkg.utils.context.get_config() if not config.report_usage: return res = requests.get("http://reports.rockchin.top:18989/usage?service_name=qchatgpt.{}&version={}&count={}&msg_source={}".format(subservice_name, self.version_str, count, config.msg_source_adapter)) if res.status_code != 200 or res.text != "ok": logging.warning("report to server failed, status_code: {}, text: {}".format(res.status_code, res.text)) except: return def get_usage(self, key_md5): return self.usage[key_md5] if key_md5 in self.usage else {} def report_text_model_usage(self, model, total_tokens): """调用方报告文字模型请求文字使用量""" key_md5 = pkg.utils.context.get_openai_manager().key_mgr.get_using_key_md5() # 以key的md5进行储存 if key_md5 not in self.usage: self.usage[key_md5] = {} if "text" not in self.usage[key_md5]: self.usage[key_md5]["text"] = {} if model not in self.usage[key_md5]["text"]: self.usage[key_md5]["text"][model] = 0 length = total_tokens self.usage[key_md5]["text"][model] += length self.dump_to_db() self.report_to_server("text", length) def report_image_model_usage(self, size): """调用方报告图片模型请求图片使用量""" key_md5 = pkg.utils.context.get_openai_manager().key_mgr.get_using_key_md5() if key_md5 not in self.usage: self.usage[key_md5] = {} if "image" not in self.usage[key_md5]: self.usage[key_md5]["image"] = {} if size not in self.usage[key_md5]["image"]: self.usage[key_md5]["image"][size] = 0 self.usage[key_md5]["image"][size] += 1 self.dump_to_db() self.report_to_server("image", 1) def get_text_length_of_key(self, key): """获取指定api-key (明文) 的文字总使用量(本地记录)""" key_md5 = hashlib.md5(key.encode('utf-8')).hexdigest() if key_md5 not in self.usage: return 0 if "text" not in self.usage[key_md5]: return 0 # 遍历其中所有模型,求和 return sum(self.usage[key_md5]["text"].values()) def get_image_count_of_key(self, key): """获取指定api-key (明文) 的图片总使用量(本地记录)""" key_md5 = hashlib.md5(key.encode('utf-8')).hexdigest() if key_md5 not in self.usage: return 0 if "image" not in self.usage[key_md5]: return 0 # 遍历其中所有模型,求和 return sum(self.usage[key_md5]["image"].values()) def get_total_text_length(self): """获取所有api-key的文字总使用量(本地记录)""" total = 0 for key in self.usage: if "text" not in self.usage[key]: continue total += sum(self.usage[key]["text"].values()) return total def dump_to_db(self): pkg.utils.context.get_database_manager().dump_usage_json(self.usage) def load_from_db(self): json_str = pkg.utils.context.get_database_manager().load_usage_json() if json_str is not None: self.usage = json.loads(json_str)